摘要 : 文章參考http://www.cocoachina.com/ios/20160803/17275.html
一開(kāi)始我一直以為拷貝方式只有兩種,并且對(duì)這兩種的拷貝方式也是分不清,然后就在網(wǎng)上學(xué)習(xí)了一下,寫一下自己的心得體會(huì),給大家分享一下.
首先 . OC對(duì)象的拷貝方式不是兩種而是三種.分別是
淺拷貝(shallow copy):在淺拷貝操作時(shí), 對(duì)于被復(fù)制的對(duì)象的每一層都是指針復(fù)制,并沒(méi)有對(duì)物理地址進(jìn)行復(fù)制,所以并不會(huì)重新開(kāi)辟新的空間.
深復(fù)制(one-level-deep copy):在深復(fù)制操作的時(shí)候,是把對(duì)象的給復(fù)制過(guò)來(lái),至少有一層是深復(fù)制.其實(shí)也不全是深復(fù)制,如果數(shù)據(jù)有很多層次,它就只復(fù)制了第一層,而第二層還是淺復(fù)制.
完全復(fù)制(real - deep copy):完全復(fù)制操作的時(shí)候,就是對(duì)于對(duì)象的每一層都進(jìn)行了復(fù)制,不僅物理地址復(fù)制,對(duì)象也復(fù)制.這才是真正的深拷貝.
圖片來(lái)源http://www.cocoachina.com/ios/20160803/17275.html
從圖片可以看出 ,我發(fā)現(xiàn)可變的對(duì)象 雖然只是用了copy ,但發(fā)現(xiàn)它并不是淺拷貝,而是深拷貝.但參數(shù)的類型竟然發(fā)生了改變,具體原因我也不清楚 ,如有大神 知道,可以幫小弟講解一下.
理解深復(fù)制(mutableCopy)
說(shuō)多無(wú)益,代碼才是王道.
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);
打印出來(lái)的結(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
)
)
試了一下又開(kāi)了一下原文講的才知道,原來(lái)這就是深復(fù)制和完全復(fù)制的區(qū)別.
對(duì)于深復(fù)制,我一直認(rèn)為,深復(fù)制就是對(duì)于原有對(duì)象的內(nèi)容直接克隆過(guò)去,但代碼顯示的結(jié)果卻讓我產(chǎn)生疑惑,很是不明白,原來(lái)它只是復(fù)制一層對(duì)象,而不會(huì)復(fù)制第二層甚至更深層次的對(duì)象,其實(shí)對(duì)于這句話我是有疑問(wèn)的,既然是復(fù)制了第一層,那么這第一層是說(shuō)的A,B,C,D呢還是就是原本array1的層次,就是一個(gè)空的對(duì)象,但看代碼執(zhí)行的結(jié)果,我的想法應(yīng)該是對(duì)的,這個(gè)層次,對(duì)于我來(lái)說(shuō),好像并不是很清楚,同樣如果有大神知道,可以講解一下.
代碼array2 = [array1 mutableCopy]; 只是對(duì)數(shù)組array1 本身進(jìn)行內(nèi)容的拷貝.但里面的字符串對(duì)象沒(méi)有進(jìn)行內(nèi)容的拷貝,而是進(jìn)行的淺復(fù)制,只是指針的復(fù)制,對(duì)象還是公用的所以改變一個(gè)也會(huì)改變所有.
看來(lái)解決這個(gè)問(wèn)題只能再看原文章了
換了復(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)沒(méi)有問(wèn)題 但我總感覺(jué) 還是有問(wè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ù)制了一層,而下面的一層卻沒(méi)有復(fù)制.
看來(lái)我的試一下完全復(fù)制這個(gè)方法了.原來(lái)完全復(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ù)制 就不在自己寫了 感覺(jué)并不是很難,就直接用原作者的.
類復(fù)制說(shuō)完了對(duì)象的復(fù)制辽慕,我們來(lái)看看如何實(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ì)影響我們給該屬性賦的值,為什么呢酌呆?
下面我們來(lái)看看
如上圖所示衡载,string2的屬性是copy類型,可以看到是無(wú)法被修改的隙袁。
因?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。