前提條件,我們?cè)谟懻搶傩缘膮?shù)問題喧锦。屬性參數(shù)是干嘛的?為什么會(huì)有屬性參數(shù)衬横?
屬性左右內(nèi)存。在設(shè)計(jì)類的時(shí)候终蒂,我們應(yīng)該充分運(yùn)用屬性來封裝數(shù)據(jù)蜂林,而數(shù)據(jù)就一定是要有存儲(chǔ)空間存儲(chǔ)的。而對(duì)于這些內(nèi)存的操作拇泣,是多種多樣的噪叙,我們?cè)诼暶鲗傩詴r(shí),必須要指明其內(nèi)存的操作方式霉翔,也就是其封裝的數(shù)據(jù)的操作方式(對(duì)象也是為了數(shù)據(jù)而生睁蕾,面向?qū)ο缶褪敲嫦驍?shù)據(jù)),便于內(nèi)存空間的管理债朵。
當(dāng)我們創(chuàng)建一個(gè)對(duì)象時(shí)子眶,會(huì)給該對(duì)象創(chuàng)建屬于自己的內(nèi)存空間,其中會(huì)為其屬性創(chuàng)建對(duì)應(yīng)的內(nèi)存空間序芦。
assign:將數(shù)值復(fù)制到當(dāng)前對(duì)象的內(nèi)存屬性空間中臭杰,該內(nèi)存空間的引用計(jì)數(shù)恒為1。同時(shí)谚中,不會(huì)對(duì)賦值源的引用計(jì)數(shù)產(chǎn)生影響渴杆。也就是說,被該關(guān)鍵字修飾的屬性內(nèi)存空間的引用計(jì)數(shù)永遠(yuǎn)是1宪塔。注意将塑,這個(gè)屬性只適用于基本數(shù)據(jù)類型,不能用于對(duì)象的操作(字符串蝌麸,數(shù)組,字典等都是對(duì)象)
copy:
深拷貝和淺拷貝:淺拷貝就是指針拷貝艾疟;深拷貝就是內(nèi)容拷貝
NSArray copy -> NSArray
NSMutableArray copy -> NSArray
NSString copy -> NSString
NSMutableString copy -> NSString
NSArray mutableCopy -> NSMutableArray
NSMutableArray mutableCopy -> NSMutableArray
NSString mutableCopy -> NSMutableString
NSMutableString mutableCopy -> NSMutableString
對(duì) immtable 類進(jìn)行 copy 来吩、 mutableCopy 得到的結(jié)果是不一樣得, mutableCopy 之后我們得到了一個(gè) NSArray 的可變版本蔽莱,并且內(nèi)存地址與原始的 array 不同弟疆,說明對(duì) immutable 類進(jìn)行 mutableCopy 得到的結(jié)果進(jìn)行了內(nèi)容拷貝,但是其容器內(nèi)部的數(shù)據(jù)并沒有拷貝內(nèi)容(地址沒有變化)盗冷,也就是說怠苔,拷貝了一個(gè)殼; 而對(duì) immutable 類進(jìn)行 copy 操作仪糖,與原始的 array 是一毛一樣柑司, 也就是我們常說的迫肖,拷貝了一份指針。
對(duì)于一個(gè) mutable 類型的對(duì)象來說攒驰,不論進(jìn)行的是 copy 還是 mutableCopy 操作蟆湖,其地址 Address 都不一樣, 而其容器中的內(nèi)容不變玻粪。則隅津,對(duì)一個(gè) mutable 類型的對(duì)象進(jìn)行 copy 或者是 mutableCopy ,都拷貝了一個(gè)殼劲室,而容器內(nèi)的數(shù)據(jù)不會(huì)進(jìn)行拷貝內(nèi)容的操作伦仍。
淺copy,類似strong很洋,持有原始對(duì)象的指針充蓝,會(huì)使retainCount加一。淺copy和strong引用的區(qū)別僅僅是淺copy多執(zhí)行一步copyWithZone:方法蹲缠。
關(guān)鍵點(diǎn):找準(zhǔn)源對(duì)象類型才能分清copy 是淺拷貝還是深拷貝
不管是集合類對(duì)象棺克,還是非集合類對(duì)象,接收到copy和mutableCopy消息時(shí)线定,都遵循以下準(zhǔn)則:
copy返回imutable對(duì)象娜谊;mutableCopy返回mutable對(duì)象;
對(duì)copy返回值使用mutable對(duì)象接口就會(huì)crash
系統(tǒng)非集合類對(duì)象指的是 NSString, NSNumber ... 之類的對(duì)象
在非集合類對(duì)象中:
對(duì)immutable對(duì)象進(jìn)行copy操作斤讥,是指針復(fù)制纱皆,mutableCopy操作時(shí)內(nèi)容復(fù)制;
對(duì)mutable對(duì)象進(jìn)行copy和mutableCopy都是內(nèi)容復(fù)制芭商。
集合類的對(duì)象自身的 shallow copy 和 deep copy
我著重強(qiáng)調(diào) “對(duì)象自身” 是因?yàn)檫@里對(duì)象 是集合類型的派草,它具有存儲(chǔ)其它對(duì)象的能力, 對(duì)象自身 和 對(duì)象內(nèi)的元素 執(zhí)行的 copy操作是不同的铛楣。這里我們先看“對(duì)象自身”近迁,后面 我們會(huì)講 “對(duì)象內(nèi)的元素” copy操作。
集合類對(duì)象是指NSArray簸州、NSDictionary鉴竭、NSSet ... 之類的對(duì)象
在集合類對(duì)象中,對(duì)immutable對(duì)象進(jìn)行copy岸浑,是指針復(fù)制搏存,mutableCopy是內(nèi)容復(fù)制;對(duì)mutable對(duì)象進(jìn)行copy和mutableCopy都是內(nèi)容復(fù)制矢洲。但是:集合對(duì)象的內(nèi)容復(fù)制僅限于對(duì)象本身璧眠,對(duì)象元素仍然是指針復(fù)制。
對(duì)(集合類) 對(duì)象自身執(zhí)行深copy,對(duì) (集合類)對(duì)象內(nèi)部的元素 執(zhí)行淺copy责静,稱為集合類的單層深復(fù)制袁滥。
NSMutableString*mutableString1 = [NSMutableStringstringWithString:@"1"];
NSMutableString*mutalbeString2 = [NSMutableStringstringWithString:@"1"];
NSMutableArray*mutableArr = [NSMutableArrayarrayWithObjects:mutalbeString2,nil];
// mutableString1和mutableArr放入NSArray
NSMutableArray*testArr = [NSMutableArrayarrayWithObjects:mutableString1, mutableArr,nil];
NSArray*testArrCopy = [[NSArrayalloc]initWithArray:testArrcopyItems:YES];
NSLog(@"數(shù)組自身地址%p %p", testArr,&testArr);
NSLog(@"數(shù)組自身地址%p", testArrCopy);NSLog(@"查看數(shù)組內(nèi)部元素的地址---------------");
NSLog(@"%p", testArr[0]);NSLog(@"%p", testArrCopy[0]);
NSLog(@"%p", testArr[1]);NSLog(@"%p", testArrCopy[1]);
NSLog(@"查看數(shù)組中包含的數(shù)組中的元素的地址---------------");
// mutableArr中的元素對(duì)比,即mutalbeString2對(duì)比
NSLog(@"%p", testArr[1][0]);
NSLog(@"%p", testArrCopy[1][0]);
initWithArray: copyItems:會(huì)使NSArray中元素均執(zhí)行copy方法泰演。這也是我在testArr中放入NSMutableArray和NSMutableString的原因呻拌。如果我放入的是NSArray或者NSString,執(zhí)行copy后睦焕,只會(huì)發(fā)生指針復(fù)制藐握;如果我放入的是未實(shí)現(xiàn)NSCopying協(xié)議的對(duì)象,調(diào)用這個(gè)方法會(huì)crash垃喊。
查看內(nèi)存猾普,數(shù)組和數(shù)組中的元素(非數(shù)組的)都進(jìn)行了深拷貝,但是mutalbeString2的指針地址均沒有變化本谜,仍然是淺拷貝初家。所以這里的 深拷貝不是完全深拷貝 可以理解為 雙層深復(fù)制
完全深復(fù)制? (完美copy)
如果想 完美的解決NSArray嵌套NSArray這種情形,使用歸檔乌助、解檔的方式
NSMutableString*mutableString1 = [NSMutableStringstringWithString:@"1"];
NSMutableString*mutalbeString2 = [NSMutableStringstringWithString:@"1"];
NSMutableArray*mutableArr = [NSMutableArrayarrayWithObjects:mutalbeString2,nil];
// mutableString1和mutableArr放入NSArray
NSMutableArray*testArr = [NSMutableArrayarrayWithObjects:mutableString1, mutableArr,nil];
NSArray*testArrCopy = [NSKeyedUnarchiverunarchiveObjectWithData:[NSKeyedArchiverarchivedDataWithRootObject:testArr]];
NSLog(@"數(shù)組自身地址%p %p", testArr,&testArr);
NSLog(@"數(shù)組自身%p", testArrCopy);
NSLog(@"查看數(shù)組內(nèi)部元素的地址---------------");
NSLog(@"%p", testArr[0]);
NSLog(@"%p", testArrCopy[0]);
NSLog(@"%p", testArr[1]);
NSLog(@"%p", testArrCopy[1]);
NSLog(@"查看數(shù)組中包含的數(shù)組中的元素的地址---------------");
// mutableArr中的元素對(duì)比溜在,即mutalbeString2對(duì)比
NSLog(@"%p", testArr[1][0]);
NSLog(@"%p", testArrCopy[1][0]);
NSLog(@"修改元素---------------");
testArrCopy[1][0] =@"111";
NSLog(@"%@", testArr[1][0]);
NSLog(@"%@", testArrCopy[1][0]);
查看內(nèi)存,可見完成了完全深復(fù)制他托,testArr和testArrCopy中的元素掖肋,以及容器中容器的指針地址完全不同,所以完成了完全深復(fù)制赏参。testArr和testArrCopy數(shù)組內(nèi)的元素值修改互不影響志笼。
這里使用歸檔和解檔的前提是NSArray中所有的對(duì)象(NSString)都實(shí)現(xiàn)了NSCoding協(xié)議。(如果是你自定義的對(duì)象把篓,你需要單獨(dú)實(shí)現(xiàn)NSCoding協(xié)議 )
作為屬性:
用 strong 和 copy 修飾的屬性會(huì)被 copy
用 weak 和 assign 修飾的屬性不會(huì)被 copy
retain
readonly
readwrite
nonatomic
atomic