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
操作,然后再加入到新的對象中。