貓貓整理問題之:copy,對象自訂copy,自訂copy
貓貓分享,必須精品
原文地址:http://blog.csdn.net/u013357243?viewmode=contents
copycopy的正目的
copy 目的:建立一個副本,彼此修改,各不干擾
Copy(不可變)和MutableCopy(可變)針對Foundation架構的資料類型。
對於自訂類,copy就是可變的。
可變數組的copy
這裡用NSMutableArray為例子。
// 可變=》可變&不可變,記憶體位址都會變化void copyDemo1(){ NSMutableArray *arrayM = [NSMutableArray arrayWithObjects:@(1), @(2), nil]; NSLog(@"%@ %p %@", arrayM, arrayM, arrayM.class); // 1. 可變 => 可變 NSMutableArray *aM = [arrayM mutableCopy]; NSLog(@"%@ %p %@", aM, aM, aM.class); // 2. 可變 => 不可變 NSArray *a = [arrayM copy]; NSLog(@"%@ %p %@", a, a, a.class);}
由結果我們得到一下結論
1:arrayM,aM,a是三個不同的對象
2:可變 => 可變 (arrayM是可變的,用mutableCopy給aM 得出aM.class是NSArrayM )
3:可變 => 不可變(aM是可變的,用copy給a 得出a.class是NSArrayI)
不可變數組的copy
void copyDemo2(){ NSArray *array = @[@(1), @(2)]; NSLog(@"%@ %p %@", array, array, array.class); // 1. 不可變 => 可變 NSMutableArray *aM = [array mutableCopy]; NSLog(@"%@ %p %@", aM, aM, aM.class); // 2. 不可變 => 不可變(淺複製) // 指標的複製,引用計數+1 NSArray *a = [array copy]; NSLog(@"%@ %p %@", a, a, a.class);}
由上結果我們得到結論
1:不可變 => 可變 記憶體位址變了,class由NSArrayI=>NSArrayM
2:不可變 => 不可變 記憶體位址一致,class由NSArrayI=>NSArrayI
作用是指標的複製,引用計數+1。術語(淺複製)
3:淺複製:不可變=>不可變 深複製:其他三種情況! (在這裡記憶時候記住都不能改就是淺複製,能改就是深複製,相對於記憶四中情況更容易記憶。)
哪裡用的最多呢?
這裡用的最多
@property (nonatomic, copy) NSString *name;
NSString
Block
都使用copy屬性,copy屬性,在賦值時,會預設做一次copy操作,讓他變成“不可變的類型”strong相當於MRC中的retain,在賦值時,只是引用計數+1
在@property中使用什麼楊的類型說明他,他就有什麼樣的方法。
例如這段代碼:
NSMutableString *strM = [NSMutableString stringWithString:@"zhangsan"]; NSLog(@"%@ %p %@", strM, strM, strM.class); Person *p = [[Person alloc] init]; p.name = strM; NSLog(@"%@ %p %@", p.name, p.name, p.name.class); // 修改"源",p.name會跟著修改 [strM setString:@"lisi"]; NSLog(@"==== %@ %p", strM, strM); NSLog(@"%@ %p", p.name, p.name);
如果用strong來說明person的name,當我們修改strM的時候,p.name也會跟著改,如果用的時copy的話,那麼他就不會被修改。這裡取決於Person類中的@property
簡單理解,如果用了copy就是複製一個String給name
而如果用了strong,就僅僅是引用計數+1。
p.name能不能修改呢?這裡我們不能直接修改,我們需要用一個萬能指標。
// 修改p.name id obj = p.name; [obj setString:@"wangwu"]; NSLog(@"==== %@ %p", strM, strM); NSLog(@"%@ %p", p.name, p.name);
這要用strong能改,這樣類會變得不安全。我們把strong改成copy
當我們修改“源”的時候
[strM setString:@"lisi"];
p.name還是原樣的。
而這時候修改屬性的方法編譯沒有問題,但是運行時候會報錯
Attempt to mutate immutable object with xxx
視圖修改一個不可變的類型,使用方法xxx
對於”可變類型”的屬性,不要使用copy描述符定義,否則賦值後,就是不可變了!
copy自訂對象[object copy]
想要讓對象能用copy方法 [p copy]
(自訂對象要實現copy功能)
1> 遵守NSCopying協議(本質上就是方便程式員編寫代碼時候,有快捷提示)
2> 實現- (id)copyWithZone:(NSZone *)zone
(zone,地區,很少用)
所有的copy方法,最終都會調用copyWithZone方法
copy操作一個對象,複製給一個新的對象。
- (id)copyWithZone:(NSZone *)zone{ // 1> 執行個體化對象,self 是對象 // self.class能夠保證繼承的子類同樣使用copy方法 Person *p = [[self.class alloc] init]; // 2> 給屬性賦值 p.name = self.name; p.age = self.age; // 3> 返回新對象 return p;}
這時候我們這樣調用
void copyDemo5(){ Person *p = [[Person alloc] init]; p.name = @"zhangsan"; p.age = 18; NSLog(@"%@", p); Person *p1 = [p copy]; p1.name = @"lisi"; NSLog(@"%@", p1);}
這時候我們就能調用自己定義的類對象的copy方法了,並且可以產生一個對象。
注意:這裡的p1.name = @”lisi”並不是修改,而是重新賦值。不要讓copy給弄迷糊了。
ps:建立iOS交流學習群:304570962
可以加貓貓QQ:1764541256 或則znycat
讓我們一起努力學習吧。
原文:http://blog.csdn.net/u013357243?viewmode=contents