摘要 : 文章參考http://www.cocoachina.com/ios/20160803/17275.html
一開始我一直以為拷貝方式只有兩種,并且對(duì)這兩種的拷貝方式也是分不清,然后就在網(wǎng)上學(xué)習(xí)了一下,寫一下自己的心得體會(huì),給大家分享一下.
首先 . OC對(duì)象的拷貝方式不是兩種而是三種.分別是
淺拷貝(shallow copy):在淺拷貝操作時(shí), 對(duì)于被復(fù)制的對(duì)象的每一層都是指針復(fù)制,并沒有對(duì)物理地址進(jìn)行復(fù)制,所以并不會(huì)重新開辟新的空間.
深復(fù)制(one-level-deep copy):在深復(fù)制操作的時(shí)候,是把對(duì)象的給復(fù)制過來,至少有一層是深復(fù)制.其實(shí)也不全是深復(fù)制,如果數(shù)據(jù)有很多層次,它就只復(fù)制了第一層,而第二層還是淺復(fù)制.
完全復(fù)制(real - deep copy):完全復(fù)制操作的時(shí)候,就是對(duì)于對(duì)象的每一層都進(jìn)行了復(fù)制,不僅物理地址復(fù)制,對(duì)象也復(fù)制.這才是真正的深拷貝.
圖片來源http://www.cocoachina.com/ios/20160803/17275.html

從圖片可以看出 ,我發(fā)現(xiàn)可變的對(duì)象 雖然只是用了copy ,但發(fā)現(xiàn)它并不是淺拷貝,而是深拷貝.但參數(shù)的類型竟然發(fā)生了改變,具體原因我也不清楚 ,如有大神 知道,可以幫小弟講解一下.

理解深復(fù)制(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);
打印出來的結(jié)果卻讓人想不明白
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
)
)
試了一下又開了一下原文講的才知道,原來這就是深復(fù)制和完全復(fù)制的區(qū)別.
對(duì)于深復(fù)制,我一直認(rèn)為,深復(fù)制就是對(duì)于原有對(duì)象的內(nèi)容直接克隆過去,但代碼顯示的結(jié)果卻讓我產(chǎn)生疑惑,很是不明白,原來它只是復(fù)制一層對(duì)象,而不會(huì)復(fù)制第二層甚至更深層次的對(duì)象,其實(shí)對(duì)于這句話我是有疑問的,既然是復(fù)制了第一層,那么這第一層是說的A,B,C,D呢還是就是原本array1的層次,就是一個(gè)空的對(duì)象,但看代碼執(zhí)行的結(jié)果,我的想法應(yīng)該是對(duì)的,這個(gè)層次,對(duì)于我來說,好像并不是很清楚,同樣如果有大神知道,可以講解一下.
代碼array2 = [array1 mutableCopy]; 只是對(duì)數(shù)組array1 本身進(jìn)行內(nèi)容的拷貝.但里面的字符串對(duì)象沒有進(jìn)行內(nèi)容的拷貝,而是進(jìn)行的淺復(fù)制,只是指針的復(fù)制,對(duì)象還是公用的所以改變一個(gè)也會(huì)改變所有.
看來解決這個(gè)問題只能再看原文章了
換了復(fù)制方式的代碼 結(jié)果還是可人的.
array2 = [[NSMutableArray alloc]initWithArray:array1 copyItems:YES];
顯示結(jié)果是
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
)
)
發(fā)現(xiàn)沒有問題 但我總感覺 還是有問題,
str = array1[4][1];
方法一變發(fā)現(xiàn)打印的結(jié)果又和上面的一樣
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];僅僅只是復(fù)制了一層,而下面的一層卻沒有復(fù)制.
看來我的試一下完全復(fù)制這個(gè)方法了.原來完全復(fù)制是歸檔和解檔啊.
array2 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:array1]];
輸出的結(jié)果是
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
)
)
大功告成!!!!!
類的復(fù)制 就不在自己寫了 感覺并不是很難,就直接用原作者的.
類復(fù)制說完了對(duì)象的復(fù)制,我們來看看如何實(shí)現(xiàn)類的復(fù)制,因?yàn)楸容^簡(jiǎn)單,直接放上代碼定義類復(fù)制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
調(diào)用
Person *person = [[Person alloc]init];
person.age = @"dsdsd";
person.name = @"dsdsdddww";
Person *copyPerson = [person copy];?
NSLog(@"%@-----%@",copyPerson.age, copyPerson.name);可以看到copyPerson的兩個(gè)屬性和persona一樣。
@property中的copy關(guān)鍵字
在設(shè)置NSString類型的屬性的時(shí)候,我們最好設(shè)置為copy類型,這樣別人使用我們定義的屬性的時(shí)候,他不管怎么改動(dòng)該屬性的賦值,都不會(huì)影響我們給該屬性賦的值,為什么呢?
下面我們來看看

如上圖所示,string2的屬性是copy類型,可以看到是無法被修改的。
因?yàn)榇藭r(shí)string2和copystring的內(nèi)存地址不一樣,修改一個(gè),不會(huì)影響另外一個(gè)。

上圖所示,如果string2的屬性是strong類型,就可以被修改,如下圖所示:因?yàn)榇藭r(shí)string2和copystring的內(nèi)存地址都是一樣的,修改一個(gè),兩個(gè)就同時(shí)被修改copy關(guān)鍵字的NSMutableString崩潰

原因:copy關(guān)鍵字的string的setter方法實(shí)際上是把參數(shù)copy之后再賦值給變量_string,那么此時(shí)變量_string雖然被申明為NSMutableString,但是copy之后,就把變量_string變成了不可變的NSString類型,所以就會(huì)出現(xiàn)方法報(bào)錯(cuò),提示對(duì)不可變的NSString使用了NSMutableString的方法appendString。