浅谈iOS中几个常用协议 NSCopying/NSMutableCopying
1、几点说明
说到NSCopying和NSMutableCopying协议,不得不说的就是copy和mutableCopy。
如果类想要支持copy操作,则必须实现NSCopying协议,也就是说实现copyWithZone方法;
如果类想要支持mutableCopy操作,则必须实现NSMutableCopying协议,也就是说实现mutableCopyWithZone方法;
iOS系统中的一些类已经实现了NSCopying或者NSMutableCopying协议的方法,如果向未实现相应方法的系统类或者自定义类发送copy或者mutableCopy消息,则会crash。
***Terminatingappduetouncaughtexception'NSInvalidArgumentException',reason:'-[PersoncopyWithZone:]:unrecognizedselectorsenttoinstance0x6080000314c0'
发送copy和mutableCopy消息,均是进行拷贝操作,但是对不可变对象的非容器类、可变对象的非容器类、可变对象的容器类、不可变对象的容器类中复制的方式略有不同;但如下两点是相同的:
发送copy消息,拷贝出来的是不可变对象;
发送mutableCopy消息,拷贝出来的是可变对象;
故如下的操作会导致crash
NSMutableString*test1=[[NSMutableStringalloc]initWithString:@"11111"]; NSMutableString*test2=[test1copy]; [test2appendString:@"22222"];
***Terminatingappduetouncaughtexception'NSInvalidArgumentException',reason:'-[NSTaggedPointerStringappendString:]:unrecognizedselectorsentto
2、系统非容器类
系统提供的非容器类中,如NSString,NSMutableString,有如下特性:
向不可变对象发送copy,进行的是指针拷贝;向不可变对象发送mutalbeCopy消息,进行的是内容拷贝;
NSString*test3=@"111111"; NSString*test4=[test3copy]; NSMutableString*test5=[test3mutableCopy]; NSLog(@"test3is%p,test4is%p,tast5is%p",test3,test4,test5); test3is0x10d6bb3a8,test4is0x10d6bb3a8,tast5is0x600000073e80
向可变对象发送copy和mutableCopy消息,均是深拷贝,也就是说内容拷贝;
NSMutableString*test11=[[NSMutableStringalloc]initWithString:@"444444"]; NSString*test12=[test11copy]; NSMutableString*test13=[test11mutableCopy]; NSLog(@"test11is%p,test12is%p,tast13is%p",test11,test12,test13); test11is0x600000073e00,test12is0xa003434343434346,tast13is0x600000073dc0
3、系统容器类
系统提供的容器类中,如NSArray,NSDictionary,有如下特性:
不可变对象copy,是浅拷贝,也就是说指针复制;发送mutableCopy,是深复制,也就是说内容复制;
NSArray*array=[NSArrayarrayWithObjects:@"1",nil]; NSArray*copyArray=[arraycopy]; NSMutableArray*mutableCopyArray=[arraymutableCopy]; NSLog(@"arrayis%p,copyArrayis%p,mutableCopyArrayis%p",array,copyArray,mutableCopyArray); arrayis0x60800001e580,copyArrayis0x60800001e580,mutableCopyArrayis0x608000046ea0
可变对象copy和mutableCopy均是单层深拷贝,也就是说单层的内容拷贝;
NSMutableArray*element=[NSMutableArrayarrayWithObject:@1]; NSMutableArray*array=[NSMutableArrayarrayWithObject:element]; NSArray*copyArray=[arraycopy]; NSMutableArray*mutableCopyArray=[arraymutableCopy]; NSLog(@"arrayis%p,copyArrayis%p,mutableCopyArrayis%p",array,copyArray,mutableCopyArray); [mutableCopyArray[0]addObject:@2]; NSLog(@"elementis%@,arrayis%@,copyArrayis%@,mutableCopyArrayis%@",element,array,copyArray,mutableCopyArray); 2017-02-2211:53:25.286test[91520:3915695]arrayis0x600000057670,copyArrayis0x600000000bc0,mutableCopyArrayis0x6080000582a0 2017-02-2211:53:25.287test[91520:3915695]elementis( 1, 2 ),arrayis( ( 1, 2 ) ),copyArrayis( ( 1, 2 ) ),mutableCopyArrayis( ( 1, 2 ) )
4、自定义的类
重要说明:
1、所以的代码设计均是针对业务需求。
2、对于自定义的类,决定能否向对象发送copy和mutableCopy消息也是如此;
1、@property声明中用copy修饰
不得不说下copy和strong在复制时候的区别,此处不讲引用计数的问题。
copy:拷贝一份不可变副本赋值给属性;所以当原对象值变化时,属性值不会变化;
strong:有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性;
@interfacePerson:NSObject @property(nonatomic,copy)NSString*familyname; @property(nonatomic,strong)NSString*nickname; @end Person*p1=[[Personalloc]init]; NSMutableString*familyname=[[NSMutableStringalloc]initWithString:@"张三"]; p1.familyname=familyname; [familynameappendString:@"峰"]; NSLog(@"p1.familynameis%@",p1.familyname); NSMutableString*nickname=[[NSMutableStringalloc]initWithString:@"二狗"]; p1.nickname=nickname; [nicknameappendString:@"蛋儿"]; NSLog(@"p1.nicknameis%@",p1.nickname); 2017-02-2213:53:58.979test[98299:3978965]p1.familynameis张三 2017-02-2213:53:58.979test[98299:3978965]p1.nicknameis二狗蛋儿
2、类的对象的copy
此处唯一需要说明的一点就是注意类的继承。
这篇文章有非常清晰详细的说明,此处只照搬下结论:
1类直接继承自NSObject,无需调用[supercopyWithZone:zone]
2父类实现了copy协议,子类也实现了copy协议,子类需要调用[supercopyWithZone:zone]
3父类没有实现copy协议,子类实现了copy协议,子类无需调用[supercopyWithZone:zone]
4、copyWithZone方法中要调用[[[selfclass]alloc]init]来分配内存
5、NSCopying
NSCopying是对象拷贝的协议。
类的对象如果支持拷贝,该类应遵守并实现NSCopying协议。
NSCopying协议中的方法只有一个,如下: -(id)copyWithZone:(NSZone*)zone{ Person*model=[[[selfclass]allocWithZone:zone]init]; model.firstName=self.firstName; model.lastName=self.lastName; //未公开的成员 model->_nickName=_nickName; returnmodel; }
3、NSMutableCopying
当自定义的类有一个属性是可变对象时,对此属性复制时要执行mutableCopyWithZone操作。
-(id)copyWithZone:(NSZone*)zone{ AFHTTPRequestSerializer*serializer=[[[selfclass]allocWithZone:zone]init]; serializer.mutableHTTPRequestHeaders=[self.mutableHTTPRequestHeadersmutableCopyWithZone:zone]; serializer.queryStringSerializationStyle=self.queryStringSerializationStyle; serializer.queryStringSerialization=self.queryStringSerialization; returnserializer; }
以上这篇浅谈iOS中几个常用协议NSCopying/NSMutableCopying就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。