前段時間突然被問到copy關鍵字的作用以及產生的效果,現在就來討論討論。
首先闡述兩個概念:
深複製:就是說複製時除了指針本身,對象內容也被複制了一份
淺複製:就是說只是複製了指針本身,對象內容並沒有被複制
一.集合對象的複製
以數組類型爲例,假設現在有一個數組:
NSArray *array =[NSArray arrayWithObjects:[Person new],[Person new],[Person new],[Person new], nil];
這個數組本身是不可變的,所以在調用copy方法時,就會是淺複製。
調用mutableCopy時,則是深複製,會生成一個新的可變數組,但是數組內部Person對象並沒有被複制。
如若是一個可變數組:
NSMutableArray *mutableArray =[NSMutableArray arrayWithObjects:[Person new],[Person new],[Person new],[Person new], nil];
這個數組在調用copy和mutableCopy的效果是一樣的,都是深複製,但是copy方法得到的是新的不可變數組對象,而mutableCopy方法得到的是新的可變數組對象。同上數組內部Person對象並沒有被複制。
那麼集合類型怎麼做到內部對象也深複製呢?敲黑板劃重點來了:
如若想要集合內部對象深複製就要使用系統API:
- (instancetype)initWithArray:(NSArray<ObjectType> *)array copyItems:(BOOL)flag;
使用的時候flag必須傳YES,如果flag傳的是NO,那麼集合內部對象還是淺複製,但是雖說flag傳YES是深複製,也只能複製第一層元素對象,也就是說如果是雙重數組NSArray<NSArray<Person *> *> *類型的複製,那個Person對象還是不會被複制的。
並且,如果集合內部對象需要深複製,Person對象必須實現NSCoping協議,並實現copyWithZone:方法,否則這個方法會拋異常。
結論:
數組類型/複製類型 | copy | mutableCopy |
NSArray | 淺複製 | 深複製 |
NSMutableArray | 深複製 | 深複製 |
二.自定義對象類型的複製
這個複製的話就得小心了,在使用之前必須要先實現NSCoping協議或NSMutableCoping協議,否則會因爲未實現copyWithZone:或者mutableCopyWithZone:方法而拋異常。
這個是否深複製就看方法內部如何實現的了,一般而言都是需要深複製的,不然copy就失去了它的意義。
舉個例子:
@interface Person : NSObject<NSCopying, NSMutableCopying>
@property(nonatomic, assign)NSInteger age;
@end
@implementation Person
- (nonnull id)copyWithZone:(nullable NSZone *)zone {
Person *p = [[Person allocWithZone:zone] init];
p.age = self.age;
return self;
}
- (nonnull id)mutableCopyWithZone:(nullable NSZone *)zone {
Person *p = [[Person allocWithZone:zone] init];
p.age = self.age;
return self;
}
@end
這樣的內部實現就是會深複製的了。