使用对象时经常需要拷贝它,而类只有实现NSCoping协议,才能支持拷贝操作。

//NSCopying协议方法,
//参数zone,为默认区,
- (id)copyWithZone:(nullable NSZone *)zone;
- 若想某个类支持拷贝功能(不可变immutableCopy的拷贝),只需声明该类遵从
NSCoping协议,并实现上述方法即可。
//NSMutableCopying 协议方法
- (id)mutableCopyWithZone:(nullable NSZone *)zone;
- 实现上述方法,可以让对象进行一份可变版本的拷贝,即NSString -> NSMutableString, NSArray -> NSMutableArray
copy or mutableCopy
-
copy 执行的一定是不可变版本的拷贝,哪怕NSMutableArray, NSMutableString 这类可变对象,进行
copy操作,返回对象的也是不可变的,返回对象类型本质为 NSArray, NSString 类型 -
mutableCopy 执行的是可变版本的拷贝,不论对象是可变的对象(NSMutableString, NSMutableArray),还是不可变对象(NSArray, NSString),执行
mutableCopy方法后返回对象都是可变的。 -
Foundation 框架中的所有collection类在默认情况下都执行浅拷贝,即,只拷贝容器对象本身,而不复制其中数据。
-
没有专门定义深拷贝的协议,绝大多数遵从
NSCoping协议的对象执行的都是浅拷贝。除非文档说明是深拷贝,或者自定义方法来实现。 -
针对
NSString的源码 可以确定,copy操作是浅拷贝,跟retain一样,mutableCopy是深拷贝,重新生成了一个新对象,是NSMutableString类型/* NSCopying methods */ - (id)copyWithZone:(NSZone *)zone { if (NSStringClass == Nil) NSStringClass = [NSString class]; return RETAIN(self); // return [[NSStringClass allocWithZone:zone] initWithString:self]; } /* NSMutableCopying methods */ - (id)mutableCopyWithZone:(NSZone*)zone { return [[NSMutableString allocWithZone:zone] initWithString:self]; } -
而
NSMutableString源码只有copy方法,返回的是NSString类型,重新生成了一个新的对象,是深拷贝,执行mutableCopy,实际是调用父类NSString的mutableCopy方法。-(id)copy { return [[NSString alloc] initWithString:self]; } -(id)copyWithZone:(NSZone*)zone { return [[NSString allocWithZone:zone] initWithString:self]; }
总结:
1. 只有实现NSCoping协议,才能执行copy操作
2. 如果自定义的对象分为可变与不可变版本,需要同时实现NSCoping与NSMutableCoping协议
3. 复制对象一般尽量执行浅拷贝
4. 如果对象需要深拷贝,可考虑新增一个专门执行深拷贝的方法