摘要 : 文章參考http://www.cocoachina.com/ios/20160803/17275.html
一開始我一直以為拷貝方式只有兩種,并且對這兩種的拷貝方式也是分不清,然后就在網上學習了一下,寫一下自己的心得體會,給大家分享一下.
首先 . OC對象的拷貝方式不是兩種而是三種.分別是
淺拷貝(shallow copy):在淺拷貝操作時, 對于被復制的對象的每一層都是指針復制,并沒有對物理地址進行復制,所以并不會重新開辟新的空間.
深復制(one-level-deep copy):在深復制操作的時候,是把對象的給復制過來,至少有一層是深復制.其實也不全是深復制,如果數據有很多層次,它就只復制了第一層,而第二層還是淺復制.
完全復制(real - deep copy):完全復制操作的時候,就是對于對象的每一層都進行了復制,不僅物理地址復制,對象也復制.這才是真正的深拷貝.
圖片來源http://www.cocoachina.com/ios/20160803/17275.html
從圖片可以看出 ,我發現可變的對象 雖然只是用了copy ,但發現它并不是淺拷貝,而是深拷貝.但參數的類型竟然發生了改變,具體原因我也不清楚 ,如有大神 知道,可以幫小弟講解一下.
理解深復制(mutableCopy)
說多無益,代碼才是王道.
NSMutableArray *array = [NSMutableArray arrayWithObjects:
[NSMutableString stringWithString:@"a"],
[NSMutableString stringWithString:@"b"],
[NSMutableString stringWithString:@"c"],
[NSMutableString stringWithString:@"d"],
nil];
NSMutableArray *array1 = [NSMutableArray arrayWithObjects:
[NSMutableString stringWithString:@"A"],
[NSMutableString stringWithString:@"B"],
[NSMutableString stringWithString:@"C"],
[NSMutableString stringWithString:@"D"],
array, nil];
NSMutableArray *array2 ;
NSMutableString *str;
array2 = [array1 mutableCopy];
str = array1[4][1];
[str appendString:@"-----1"];
NSLog(@"array2------%@",array2);
NSLog(@"array1------%@",array1);
打印出來的結果卻讓人想不明白
2016-08-26 12:08:38.277 深淺拷貝[1117:64610] array2------(
A,
B,
C,
D,
(
a,
"b-----1",
c,
d
)
)
2016-08-26 12:08:38.278 深淺拷貝[1117:64610] array1------(
A,
B,
C,
D,
(
a,
"b-----1",
c,
d
)
)
試了一下又開了一下原文講的才知道,原來這就是深復制和完全復制的區別.
對于深復制,我一直認為,深復制就是對于原有對象的內容直接克隆過去,但代碼顯示的結果卻讓我產生疑惑,很是不明白,原來它只是復制一層對象,而不會復制第二層甚至更深層次的對象,其實對于這句話我是有疑問的,既然是復制了第一層,那么這第一層是說的A,B,C,D呢還是就是原本array1的層次,就是一個空的對象,但看代碼執行的結果,我的想法應該是對的,這個層次,對于我來說,好像并不是很清楚,同樣如果有大神知道,可以講解一下.
代碼array2 = [array1 mutableCopy]; 只是對數組array1 本身進行內容的拷貝.但里面的字符串對象沒有進行內容的拷貝,而是進行的淺復制,只是指針的復制,對象還是公用的所以改變一個也會改變所有.
看來解決這個問題只能再看原文章了
換了復制方式的代碼 結果還是可人的.
array2 = [[NSMutableArray alloc]initWithArray:array1 copyItems:YES];
顯示結果是
2016-08-26 12:23:25.787 深淺拷貝[1195:69165] array2------(
A,
B,
C,
D,
(
a,
b,
c,
d
)
)
2016-08-26 12:23:25.787 深淺拷貝[1195:69165] array1------(
"A-----1",
B,
C,
D,
(
a,
b,
c,
d
)
)
發現沒有問題 但我總感覺 還是有問題,
str = array1[4][1];
方法一變發現打印的結果又和上面的一樣
2016-08-26 12:24:42.143 深淺拷貝[1218:70070] array2------(
A,
B,
C,
D,
(
a,
"b-----1",
c,
d
)
)
2016-08-26 12:24:42.144 深淺拷貝[1218:70070] array1------(
A,
B,
C,
D,
(
a,
"b-----1",
c,
d
)
)
唉, 還是失敗了,array2 = [[NSMutableArray alloc]initWithArray:array1 copyItems:YES];僅僅只是復制了一層,而下面的一層卻沒有復制.
看來我的試一下完全復制這個方法了.原來完全復制是歸檔和解檔啊.
array2 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:array1]];
輸出的結果是
2016-08-26 12:30:12.292 深淺拷貝[1265:72371] array2------(
A,
B,
C,
D,
(
a,
b,
c,
d
)
)
2016-08-26 12:30:12.293 深淺拷貝[1265:72371] array1------(
A,
B,
C,
D,
(
a,
"b-----1",
c,
d
)
)
大功告成!!!!!
類的復制 就不在自己寫了 感覺并不是很難,就直接用原作者的.
類復制說完了對象的復制,我們來看看如何實現類的復制,因為比較簡單,直接放上代碼定義類復制123456789101112131415#import@interface Person : NSObject@property(strong,nonatomic)NSString *age;
@property(strong,nonatomic)NSString *name;
@end
#import "Person.h"
@implementation Person
- (id)copyWithZone:(NSZone *)zone
{
Person *person = [[Person allocWithZone:zone] init];
person.age = self.age;
person.name = self.name;
return person;
}
@end
調用
Person *person = [[Person alloc]init];
person.age = @"dsdsd";
person.name = @"dsdsdddww";
Person *copyPerson = [person copy];?
NSLog(@"%@-----%@",copyPerson.age, copyPerson.name);可以看到copyPerson的兩個屬性和persona一樣。
@property中的copy關鍵字
在設置NSString類型的屬性的時候,我們最好設置為copy類型,這樣別人使用我們定義的屬性的時候,他不管怎么改動該屬性的賦值,都不會影響我們給該屬性賦的值,為什么呢?
下面我們來看看
如上圖所示,string2的屬性是copy類型,可以看到是無法被修改的。
因為此時string2和copystring的內存地址不一樣,修改一個,不會影響另外一個。
上圖所示,如果string2的屬性是strong類型,就可以被修改,如下圖所示:因為此時string2和copystring的內存地址都是一樣的,修改一個,兩個就同時被修改copy關鍵字的NSMutableString崩潰
原因:copy關鍵字的string的setter方法實際上是把參數copy之后再賦值給變量_string,那么此時變量_string雖然被申明為NSMutableString,但是copy之后,就把變量_string變成了不可變的NSString類型,所以就會出現方法報錯,提示對不可變的NSString使用了NSMutableString的方法appendString。