本文參考
- iOS淺談:深.淺拷貝與copy.strong這一篇總結(jié)的不太到位硬爆,可以繼續(xù)讀下一篇
- 在iOS中關(guān)于深拷貝和淺拷貝以及copy屬性的理解對(duì)上一篇的補(bǔ)充
- Objective-C中的深拷貝和淺拷貝這一篇很詳細(xì)
- 深拷貝與淺拷貝 Apple官方文檔
容器類和非容器類
-
容器類:數(shù)組侈百、字典完沪、集合等。
- 容器類不可變對(duì)象: 比如NSArray
- 容器類可變對(duì)象: 比如NSMutableArray
-
非容器類:字符串
- 非容器類不可變對(duì)象,比如NSString
- 非容器類可變對(duì)象:比如NSMutableString
初步解釋
-
非容器類。
- 淺拷貝:拷貝地址(對(duì)非容器類的淺拷貝就是拷貝對(duì)象的地址戏挡,對(duì)象里面存的內(nèi)容仍然是一份,沒有新的內(nèi)存被分配晨仑。)
- 深拷貝:拷貝內(nèi)容(對(duì)非容器類的深拷貝就是重新分配一塊內(nèi)存褐墅,然后把另一個(gè)對(duì)象的內(nèi)容原封不動(dòng)的給我拿過來。)
-
容器類
- 淺拷貝:生成一個(gè)新的容器(也就是“殼”)洪己,但是里面保存的元素的指針還是指向原來的元素地址妥凳。也就是說,對(duì)于容器類的淺拷貝來說答捕,容器的地址是不同的逝钥,但是里面的內(nèi)容地址是相同的,修改其中一個(gè)的內(nèi)容拱镐,會(huì)使另一個(gè)的也跟著變化艘款。(容器類的淺拷貝是對(duì)容器里的內(nèi)容不進(jìn)行拷貝齐莲,兩個(gè)容器的地址是不同的,但容器里的所裝的東西是一樣的磷箕,在一個(gè)容器中修改值,則另一個(gè)淺拷貝的容器中的值也會(huì)變化阵难。)
- 深拷貝:不光生成一個(gè)新的容器岳枷,對(duì)容器里面的元素也進(jìn)行拷貝。
immutableObject呜叫、mutableObject
immutableObject空繁,不可變對(duì)象如:NSString,NSArray等
mutableObject朱庆,可變對(duì)象例如:NSMutableString,NSMutableArray等
copy 和 mutablecopy
****copy 和 mutablecopy主要是為了生成對(duì)象的副本來使用****盛泡。
copy:copy出來的對(duì)象類型總是不可變的(例如, NSString, NSDictionary, NSArray等等)。
mutablecopy:mutableCopy拷貝出來的對(duì)象類型總是可變類型(例如, NSMutableString, NSMutableDictionary, NSMutableArray等等)
注意:產(chǎn)生一個(gè)對(duì)象的可變副本并不要求被復(fù)制的對(duì)象是可變的娱颊,同理傲诵,可變對(duì)象也可以創(chuàng)建一個(gè)不可變副本。也就是說箱硕,mutableCooy和copy對(duì)于不可變對(duì)象和可變對(duì)象都可以使用拴竹。
1.對(duì)于非容器類(非集合類)對(duì)象
-
對(duì)于不可變對(duì)象(immutableObject)
- copy,淺拷貝(指針拷貝)剧罩。返回的是一個(gè)不可變類型的對(duì)象栓拜。(只有這一個(gè)是淺拷貝,不可變對(duì)象的copy)
- mutableCopy惠昔,深拷貝(內(nèi)容拷貝)幕与。返回的是一個(gè)可變類型的對(duì)象。
-
對(duì)于可變對(duì)象(mutableObject)
- copy镇防,深拷貝(內(nèi)容拷貝)啦鸣。返回的是一個(gè)不可變類型的對(duì)象。
- mutableCopy来氧,深拷貝(內(nèi)容拷貝)赏陵。返回的是一個(gè)可變類型的對(duì)象。
[immutableObject copy] //淺拷貝
[immutableObject mutableCopy] //深拷貝
[mutableObject copy] //深拷貝
[mutableObject mutableCopy] //深拷貝
2.對(duì)于容器類(集合類)對(duì)象
-
對(duì)于不可變對(duì)象(immutableObject)
- copy饲漾,淺拷貝(指針拷貝)蝙搔。返回的是一個(gè)不可變類型的對(duì)象。(只有這一個(gè)是淺拷貝考传,不可變對(duì)象的copy)
- mutableCopy吃型,深拷貝(內(nèi)容拷貝)。返回的是一個(gè)可變類型的對(duì)象僚楞。
-
對(duì)于可變對(duì)象(mutableObject)
- copy勤晚,深拷貝(內(nèi)容拷貝)枉层。返回的是一個(gè)不可變類型的對(duì)象。
- mutableCopy赐写,深拷貝(內(nèi)容拷貝)鸟蜡。返回的是一個(gè)可變類型的對(duì)象。
用代碼簡單表示如下:(注意挺邀,容器類的淺拷貝是容器新生成揉忘,里面的元素還是指向原來的)
[immutableObject copy] //淺拷貝
[immutableObject mutableCopy] //深拷貝
[mutableObject copy] //深拷貝
[mutableObject mutableCopy] //深拷貝
strong和copy的代碼測(cè)試
- copy只能修飾不可變類型,當(dāng)修飾可變類型時(shí)端铛,編譯雖然不會(huì)出錯(cuò)泣矛,但是copy出來的是一個(gè)不可變類型對(duì)象,它被賦值給一個(gè)可變類型對(duì)象禾蚕,當(dāng)調(diào)用其方法修改其內(nèi)容時(shí)會(huì)崩潰您朽。
- 注意:*NSString,對(duì)不可變類型的指針重新賦值换淆,會(huì)改變其地址哗总。NSString str = @"xxxxxx";//地址為0x100001050;str = @"ssssss";//地址為0x1000010d0
- 所以說倍试,如果用strong修飾NSString魂奥,賦值的來源是不可變(NSString)的話,即使賦值來源的內(nèi)容被更改了易猫,也不會(huì)影響被賦值的NSString對(duì)象耻煤;copy也是如此,雖然對(duì)于賦值來源是不可變(NSString)的拷貝是淺拷貝准颓,但即使賦值來源的內(nèi)容改變了哈蝇,也不會(huì)有影響。因?yàn)橘x值來源會(huì)重新指向一個(gè)地址攘已,不是在原地址上更改內(nèi)容炮赦。
@interface Kaobei : NSObject
@property (strong,nonatomic) NSString *strStrong;
@property (copy,nonatomic) NSString *strCopy;
@end
@implementation Kaobei
- (void)test{
NSString *str = @"xxxxxx";
self.strStrong = str;
self.strCopy = str;
NSLog(@"str = %p",str); //str = 0x100001050
NSLog(@"strStrong = %p",_strStrong);//strStrong = 0x100001050
NSLog(@"strCopy = %p",_strCopy); //strCopy = 0x100001050
str = @"ssssss";
NSLog(@"str = %p",str); //str = 0x1000010d0
NSLog(@"strStrong = %p",_strStrong);//strStrong = 0x100001050
NSLog(@"strCopy = %p",_strCopy); //strCopy = 0x100001050
}
@end
使用copy而不用strong的原因
因?yàn)楦割愔羔樋梢灾赶蜃宇悓?duì)象,使用 copy 的目的是為了讓本對(duì)象的屬性不受外界影響,使用 copy 無論給我傳入是一個(gè)可變對(duì)象還是不可對(duì)象,我本身持有的就是一個(gè)不可變的副本.
如果我們使用是 strong ,那么這個(gè)屬性就有可能指向一個(gè)可變對(duì)象,如果這個(gè)可變對(duì)象在外部被修改了,那么會(huì)影響該屬性.
關(guān)于retain和copy、mutableCopy的異同點(diǎn)
retain:始終是淺拷貝样勃。引用計(jì)數(shù)每次加一吠勘。返回對(duì)象是否可變與被復(fù)制的對(duì)象保持一致。
copy:對(duì)于可變對(duì)象為深拷貝峡眶,引用計(jì)數(shù)不改變剧防;對(duì)于不可變對(duì)象是淺拷貝,引用計(jì)數(shù)每次加一辫樱。始終返回一個(gè)不可變對(duì)象峭拘。
mutableCopy:始終是深拷貝,引用計(jì)數(shù)不改變。始終返回一個(gè)可變對(duì)象鸡挠。
自定義類對(duì)象之間的深淺拷貝問題
在Objective-C中并不是所有的類都支持拷貝辉饱;只有遵循NSCopying協(xié)議的類,才支持copy拷貝拣展,只有遵循NSMutableCopying協(xié)議的類彭沼,才支持mutableCopy拷貝。如果沒有遵循拷貝協(xié)議备埃,拷貝時(shí)會(huì)出錯(cuò)姓惑。
如果我們想再我們自定義的類中支持copy和mutableCopy那么我們就需要使我們定義的類遵循NSCopying和NSMutableCopying協(xié)議,代碼如下:
@interface Test : NSObject <NSCopying, NSMutableCopying>
然后再重寫-(id) copyWithZone : (NSZone *) zone 和 -(id)mutableCopyWithZone : (NSZone *) zone
重寫-(id) copyWithZone :(NSZone *)zone方法如下
//淺拷貝
-(id) copyWithZone : (NSZone *) zone
{
return [self retain];
}
//深拷貝
-(id) mutableCopyWithZone : (NSZone *) zone
{
Test *test = [[Test allocWithZone : zone] init];
test.property = self.property;
return test;