当前位置: 移动技术网 > IT编程>移动开发>IOS > 浅谈iOS中几个常用协议 NSCopying/NSMutableCopying

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

2019年07月24日  | 移动技术网IT编程  | 我要评论

杉原杏璃qvod,网王青葱岁月,敖贤英

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就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网