NSCopying
NSCopying
是一个与对象拷贝有关的协议。如果想让一个类的对象支持拷贝,就需要让该类实现NSCopying
协议。NSCopying
协议中的声明的方法只有一个- (id)copyWithZone:(NSZone *)zone
。当我们的类实现了NSCopying
协议,通过类的对象调用copy
方法时,copy
方法就会去调用我们实现的- (id)copyWithZone:(NSZone *)zone
方法,实现拷贝功能。实现代码如下所示:
- (id)copyWithZone:(NSZone *)zone{
PersonModel *model = [[[self class] allocWithZone:zone] init];
model.firstName = self.firstName;
model.lastName = self.lastName;
//未公开的成员
model->_nickName = _nickName;
return model;
}
说明:在- (id)copyWithZone:(NSZone *)zone
方法中,一定要通过[self class]
方法返回的对象调用allocWithZone:
方法。因为指针可能实际指向的是PersonModel
的子类。这种情况下,通过调用[self class]
,就可以返回正确的类的类型对象。
NSMutableCopying
NSCopying
协议与NSMutableCopying
的区别主要是在于,返回的对象是否是可变类型的。以Foundation框架的NSArray
为例
NSArray *nameArray = @[@"Jim", @"Tom", @"David"];
NSArray *copyArray = [nameArray copy];
NSMutableArray *mutableCopyArray = [nameArray mutableCopy];
[mutableCopyArray addObject:@"Sam"];
NSArray
对象调用copy
方法时,copy
方法会调用- (id)copyWithZone:(NSZone *)zone
,得到对象的一份拷贝,但得到的对象还是不可变的对象。而NSArray
对象调用mutableCopy
方法时,mutableCopy
方法会调用- (id)mutableCopyWithZone:(NSZone *)zone
,得到可变的对象。
所以,如果自定义类具有可变和不可变的区别,想让它支持拷贝时,就需要同时实现NSCopying
和NSMutableCopying
,在- (id)copyWithZone:(NSZone *)zone
返回的是不可变对象,在- (id)mutableCopyWithZone:(NSZone *)zone
返回的是可变对象。
在拷贝对象时,需要注意拷贝执行的是浅拷贝还是深拷贝。深拷贝在拷贝对象时,会将对象的底层数据也进行了拷贝。Foundation框架中提供的所有集合,默认提供的都是浅拷贝。以上面的代码为例,对
nameArray
执行copy
时,得到一个新的数组对象。但是新对象中存放的字符串和nameArray
中存放的都是同一个字符串;若执行的是深拷贝,就会对nameArray
中的所有字符串执行copy
操作,然后再加入到新的对象中。