要向讓咱們本身建立的對象調用copy 方法,( [p copy] ) 前提條件是:程序員
1> 遵照NSCopying協議 (本質上就是方便程序員編寫代碼時候,有快捷提示)
2> 實現 - (id)copyWithZone:(NSZone *)zone數組
copy方法, 最終都會調用copyWithZone方法atom
mutablecopy方法,最終都會調用mutableCopyWithZone方法spa
有一個模型對象Personcode
@interface Person : NSObject<NSCopying,NSMutableCopying> @property(nonatomic,copy)NSString *name; @property(nonatomic,assign)NSInteger age; @end
遵照NSCopying協議 ,重寫Person 的 copyWithZone方法 和 mutableCopyWithZone copy操做一個對象,複製給一個新的對象。對象
- (id)copyWithZone:(NSZone *)zone { // 1> 實例化對象,self 是對象 // self.class可以保證繼承的子類一樣使用copy方法 Person *p = [[self.class alloc] init]; //Person * p = [[self.class allocWithZone:zone] init]; // 2> 給屬性賦值,深拷貝一份屬性[self.name copy]字符串的copy方法,賦給新對象,可是這裏不須要由於屬性是不可變字符串。 p.name = self.name; p.age = self.age; // 3> 返回新對象 return p; }
驗證: 繼承
- (void)viewDidLoad { [super viewDidLoad]; Person *p = [Person new]; Person *p2 = [p copy]; NSLog(@"%@,%@", p, p2); }
結果以下:兩個對象地址不同。哦了字符串
上面的模型屬性中不包含容器類對象,若是包含容器類對象,咱們這樣寫的話,會致使容器自己是深拷貝了,可是容器裏面盛放的對象並非深拷貝。裏面的對象依舊是淺拷貝。面對這種狀況應該這樣寫:it
有一個Person模型對象,其中有一個 NSArray屬性 table
@interface Person : NSObject<NSCopying,NSMutableCopying> @property(nonatomic,copy)NSString *name; @property(nonatomic,assign)NSInteger age; @property(nonatomic,strong)NSArray *arr; @end
重寫 Person 的 copyWithZone方法 和 mutableCopyWithZone ,注意:p.arr = 不能簡單的賦值,須要調用initWithArray: copyItems: 方法,這個方法可讓數組實現深拷貝,可是僅限於數組中沒有再嵌套容器類,若是數組中再嵌套容器類,這個方法就不行了,須要使用歸檔。
- (id)copyWithZone:(NSZone *)zone{ //實例化對象 //self.class可以保證繼承的子類能夠使用copy方法 Person * p = [[self.class alloc] init]; //給屬性賦值 p.age = self.age; p.name = self.name; //這裏要注意了,不能單純的賦值,單純的賦值,就是表明引用同一個數組,當一個數組中的元素改變了。copy的數組中也會改,因此要深copy一份數組 p.arr = [[NSArray alloc] initWithArray:self.arr copyItems:YES]; //返回新對象 return p; }
另外須要注意:initWithArray: copyItem: 這個方法調用時,self.arr中的對象 必需要具備copy的能力,否則會崩潰的,因此咱們要將數組中的元素實現copy的方法。
- (id)copyWithZone:(NSZone *)zone{ //實例化對象 //self.class可以保證繼承的子類能夠使用copy方法 pm * p = [[self.class alloc] init]; //給屬性賦值 p.days = self.days; //返回新對象 return p; } - (id)mutableCopyWithZone:(NSZone *)zone{ //實例化對象 //self.class可以保證繼承的子類能夠使用copy方法 pm * p = [[self.class alloc] init]; //給屬性賦值 p.days = self.days; //返回新對象 return p; }
驗證:
//建立數組 pm *pmm = [pm new]; pmm.days = @"one"; NSArray *array = [NSArray arrayWithObjects:pmm, nil]; //建立模型 Person *p = [Person new]; //給模型中的數組賦值 p.arr = array; //copy模型 Person *p2 = [p copy]; //修改copy後的模型數組中對象的值 [[p2.arr lastObject] setDays:@"two"] ; //打印結果 NSLog(@"%@", [[p.arr lastObject] days]); NSLog(@"%@", [[p2.arr lastObject] days]);
結果以下:修改copy後的對象中的數組屬性中的元素後, 原始的對象中的值並無變,說明copy成功了。