温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

浅谈iOS中几个常用协议 NSCopying/NSMutableCopying

发布时间:2020-09-27 06:37:26 来源:脚本之家 阅读:406 作者:小洋子 栏目:移动开发

1、几点说明

说到NSCopying和NSMutableCopying协议,不得不说的就是copy和mutableCopy。

如果类想要支持copy操作,则必须实现NSCopying协议,也就是说实现copyWithZone方法;

如果类想要支持mutableCopy操作,则必须实现NSMutableCopying协议,也就是说实现mutableCopyWithZone方法;

iOS系统中的一些类已经实现了NSCopying或者NSMutableCopying协议的方法,如果向未实现相应方法的系统类或者自定义类发送copy或者mutableCopy消息,则会crash。

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Person copyWithZone:]: unrecognized selector sent to instance 0x6080000314c0'

发送copy和mutableCopy消息,均是进行拷贝操作,但是对不可变对象的非容器类、可变对象的非容器类、可变对象的容器类、不可变对象的容器类中复制的方式略有不同;但如下两点是相同的:

发送copy消息,拷贝出来的是不可变对象;

发送mutableCopy消息,拷贝出来的是可变对象;

故如下的操作会导致crash

 NSMutableString *test1 = [[NSMutableString alloc]initWithString:@"11111"]; NSMutableString *test2 = [test1 copy]; [test2 appendString:@"22222"];

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSTaggedPointerString appendString:]: unrecognized selector sent to

2、系统非容器类

系统提供的非容器类中,如NSString,NSMutableString,有如下特性:

向不可变对象发送copy,进行的是指针拷贝;向不可变对象发送mutalbeCopy消息,进行的是内容拷贝;

 NSString *test3 = @"111111"; NSString *test4 = [test3 copy]; NSMutableString *test5 = [test3 mutableCopy]; NSLog(@"test3 is %p, test4 is %p, tast5 is %p",test3,test4,test5); test3 is 0x10d6bb3a8, test4 is 0x10d6bb3a8, tast5 is 0x600000073e80

向可变对象发送copy和mutableCopy消息,均是深拷贝,也就是说内容拷贝;

 NSMutableString *test11 = [[NSMutableString alloc]initWithString:@"444444"]; NSString *test12 = [test11 copy]; NSMutableString *test13 = [test11 mutableCopy]; NSLog(@"test11 is %p, test12 is %p, tast13 is %p",test11,test12,test13); test11 is 0x600000073e00, test12 is 0xa003434343434346, tast13 is 0x600000073dc0

3、系统容器类

系统提供的容器类中,如NSArray,NSDictionary,有如下特性:

不可变对象copy,是浅拷贝,也就是说指针复制;发送mutableCopy,是深复制,也就是说内容复制;

 NSArray *array = [NSArray arrayWithObjects:@"1", nil]; NSArray *copyArray = [array copy]; NSMutableArray *mutableCopyArray = [array mutableCopy]; NSLog(@"array is %p, copyArray is %p, mutableCopyArray is %p", array, copyArray, mutableCopyArray); array is 0x60800001e580, copyArray is 0x60800001e580, mutableCopyArray is 0x608000046ea0

可变对象copy和mutableCopy均是单层深拷贝,也就是说单层的内容拷贝;

 NSMutableArray *element = [NSMutableArray arrayWithObject:@1]; NSMutableArray *array = [NSMutableArray arrayWithObject:element]; NSArray *copyArray = [array copy]; NSMutableArray *mutableCopyArray = [array mutableCopy]; NSLog(@"array is %p, copyArray is %p, mutableCopyArray is %p", array, copyArray, mutableCopyArray); [mutableCopyArray[0] addObject:@2]; NSLog(@"element is %@, array is %@, copyArray is %@, mutableCopyArray is %@", element,array,copyArray, mutableCopyArray); 2017-02-22 11:53:25.286 test[91520:3915695] array is 0x600000057670, copyArray is 0x600000000bc0, mutableCopyArray is 0x6080000582a0 2017-02-22 11:53:25.287 test[91520:3915695] element is ( 1, 2 ), array is ( ( 1, 2 ) ), copyArray is ( ( 1, 2 ) ), mutableCopyArray is ( ( 1, 2 ) )

4、自定义的类

重要说明:

1、所以的代码设计均是针对业务需求。

2、对于自定义的类,决定能否向对象发送copy和mutableCopy消息也是如此;

1、@property 声明中用 copy 修饰

不得不说下copy和strong在复制时候的区别,此处不讲引用计数的问题。

copy:拷贝一份不可变副本赋值给属性;所以当原对象值变化时,属性值不会变化;

strong:有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性;

 @interface Person : NSObject @property (nonatomic, copy) NSString *familyname; @property (nonatomic, strong) NSString *nickname; @end Person *p1 = [[Person alloc]init]; NSMutableString *familyname = [[NSMutableString alloc]initWithString:@"张三"]; p1.familyname = familyname; [familyname appendString:@"峰"]; NSLog(@"p1.familyname is %@",p1.familyname); NSMutableString *nickname = [[NSMutableString alloc]initWithString:@"二狗"]; p1.nickname = nickname; [nickname appendString:@"蛋儿"]; NSLog(@"p1.nickname is %@", p1.nickname); 2017-02-22 13:53:58.979 test[98299:3978965] p1.familyname is 张三 2017-02-22 13:53:58.979 test[98299:3978965] p1.nickname is 二狗蛋儿

2、类的对象的copy

此处唯一需要说明的一点就是注意类的继承。

这篇文章有非常清晰详细的说明,此处只照搬下结论:

1 类直接继承自NSObject,无需调用[super copyWithZone:zone]

2 父类实现了copy协议,子类也实现了copy协议,子类需要调用[super copyWithZone:zone]

3 父类没有实现copy协议,子类实现了copy协议,子类无需调用[super copyWithZone:zone]

4、copyWithZone方法中要调用[[[self class] alloc] init]来分配内存

5、NSCopying

NSCopying是对象拷贝的协议。

类的对象如果支持拷贝,该类应遵守并实现NSCopying协议。

 NSCopying协议中的方法只有一个,如下: - (id)copyWithZone:(NSZone *)zone { Person *model = [[[self class] allocWithZone:zone] init]; model.firstName = self.firstName; model.lastName = self.lastName; //未公开的成员 model->_nickName = _nickName; return model; }

3、NSMutableCopying

当自定义的类有一个属性是可变对象时,对此属性复制时要执行mutableCopyWithZone操作。

 - (id)copyWithZone:(NSZone *)zone { AFHTTPRequestSerializer *serializer = [[[self class] allocWithZone:zone] init]; serializer.mutableHTTPRequestHeaders = [self.mutableHTTPRequestHeaders mutableCopyWithZone:zone]; serializer.queryStringSerializationStyle = self.queryStringSerializationStyle; serializer.queryStringSerialization = self.queryStringSerialization; return serializer; }

以上这篇浅谈iOS中几个常用协议 NSCopying/NSMutableCopying就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持亿速云。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI