@property的本質(zhì)
@property = ivar(實(shí)例變量)+getter + setter(存取方法)
“屬性” (property)作為 Objective-C 的一項(xiàng)特性刹枉,主要的作用就在于封裝對(duì)象中的數(shù)據(jù)建芙。 Objective-C 對(duì)象通常會(huì)把其所需要的數(shù)據(jù)保存為各種實(shí)例變量巡通。實(shí)例變量一般通過(guò)“存取方法”(access method)來(lái)訪問。其中,“獲取方法” (getter)用于讀取變量值,而“設(shè)置方法” (setter)用于寫入變量值。這個(gè)概念已經(jīng)定型佑淀,并且經(jīng)由“屬性”這一特性而成為 Objective-C 2.0 的一部分。 而在正規(guī)的 Objective-C 編碼風(fēng)格中卷要,存取方法有著嚴(yán)格的命名規(guī)范渣聚。 正因?yàn)橛辛诉@種嚴(yán)格的命名規(guī)范独榴,所以 Objective-C 這門語(yǔ)言才能根據(jù)名稱自動(dòng)創(chuàng)建出存取方法。
也可以說(shuō):@property = getter + setter;
ivar奕枝、getter棺榔、setter 是如何生成并添加到這個(gè)類中的?
完成屬性定義后,編譯器會(huì)自動(dòng)編寫訪問這些屬性所需的方法隘道,此過(guò)程叫做“自動(dòng)合成”(autosynthesis)症歇。除了生成方法代碼 getter、setter 之外谭梗,編譯器還要自動(dòng)向類中添加適當(dāng)類型的實(shí)例變量忘晤,并且在屬性名前面加下劃線,以此作為實(shí)例變量的名字激捏。
?@protocol 和 category 中如何使用 @property
在 protocol 中使用 property 只會(huì)生成 setter 和 getter 方法聲明,我們使用屬性的目的,是希望遵守我協(xié)議的對(duì)象能實(shí)現(xiàn)該屬性
category 使用 @property 也是只會(huì)生成 setter 和 getter 方法的聲明,如果我們真的需要給 category 增加屬性的實(shí)現(xiàn),需要借助于運(yùn)行時(shí)的兩個(gè)函數(shù):
1设塔,objc_setAssociatedObject
2,objc_getAssociatedObject
ARC下远舅,不顯式指定任何屬性關(guān)鍵字時(shí)闰蛔,默認(rèn)的關(guān)鍵字都有哪些?
對(duì)應(yīng)基本數(shù)據(jù)類型默認(rèn)關(guān)鍵字是
atomic,readwrite,assign
對(duì)于普通的 Objective-C 對(duì)象
atomic,readwrite,strong
用@property聲明的NSString(或NSArray图柏,NSDictionary)經(jīng)常使用copy關(guān)鍵字序六,為什么?如果改用strong關(guān)鍵字蚤吹,可能造成什么問題例诀?
重寫帶copy關(guān)鍵字的setter方法
- ?(void)setName:(NSString *)name {
? ?_name = [name copy];
}
1,因?yàn)楦割惖闹羔樋梢灾赶蜃宇惖膶?duì)象裁着,使用copy的目的是為了讓本對(duì)象的屬性不受外界影響繁涂,使用copy無(wú)論給我傳入一個(gè)可變對(duì)象還是不可變對(duì)象,我本身持有的就是一個(gè)不可變的副本二驰。
2爆土,如果我們使用時(shí)strong,那么這個(gè)屬性就有可能指向一個(gè)可變對(duì)象,如果這個(gè)可變對(duì)象在外部修改了氧猬,那么會(huì)影響該屬性,copy特質(zhì)所表達(dá)的所屬關(guān)系與strong類似盅抚,然而設(shè)置方法并不保留新值漠魏,而是將其拷貝妄均,當(dāng)屬性類型是NSString時(shí)哪自,經(jīng)常用此特質(zhì)來(lái)保護(hù)其封裝性,因?yàn)閭鬟f給設(shè)置方法的新值有可能指向一個(gè)NSMutableString類的實(shí)例壤巷,這個(gè)類是 NSString 的子類,表示一種可修改其值的字符串胧华,此時(shí)若是不拷貝字符串,那么設(shè)置完屬性之后宙彪,字符串的值就可能會(huì)在對(duì)象不知情的情況下遭人更改矩动。所以,這時(shí)就要拷貝一份“不可變” (immutable)的字符串释漆,確保對(duì)象中的字符串值不會(huì)無(wú)意間變動(dòng)悲没。只要實(shí)現(xiàn)屬性所用的對(duì)象是“可變的” (mutable),就應(yīng)該在設(shè)置新屬性值時(shí)拷貝一份男图。
深復(fù)制和淺復(fù)制
1示姿,對(duì)非集合類的對(duì)象的copy和mutableCopy操作。
在非集合類對(duì)象中享言,對(duì)不可變對(duì)象進(jìn)行copy操作峻凫,是指針復(fù)制,mutableCopy操作時(shí)是內(nèi)容復(fù)制览露。對(duì)可變對(duì)象進(jìn)行copy和mutableCopy都是內(nèi)容復(fù)制荧琼。
[immutableObject copy] // 淺復(fù)制
[immutableObject mutableCopy] //深復(fù)制
[mutableObject copy] //深復(fù)制
[mutableObject mutableCopy] //深復(fù)制
例如:
NSMutableString *string = [NSMutableString stringWithString:@"origin"];//copy
NSString *stringCopy = [string copy];
查看內(nèi)存,會(huì)發(fā)現(xiàn) string差牛、stringCopy 內(nèi)存地址都不一樣命锄,說(shuō)明此時(shí)都是做內(nèi)容拷貝、深拷貝偏化。即使你進(jìn)行如下操作:
[string appendString:@"origion!"]
stringCopy 的值也不會(huì)因此改變脐恩,但是如果不使用 copy,stringCopy 的值就會(huì)被改變侦讨。 集合類對(duì)象以此類推驶冒。 所以,
用 @property 聲明 NSString韵卤、NSArray骗污、NSDictionary 經(jīng)常使用 copy 關(guān)鍵字,是因?yàn)樗麄冇袑?duì)應(yīng)的可變類型:NSMutableString沈条、NSMutableArray需忿、NSMutableDictionary,他們之間可能進(jìn)行賦值操作,為確保對(duì)象中的字符串值不會(huì)無(wú)意間變動(dòng)屋厘,應(yīng)該在設(shè)置新屬性值時(shí)拷貝一份涕烧。
2,對(duì)集合類的對(duì)象的copy和mutableCopy操作汗洒。
集合類對(duì)象是指 NSArray议纯、NSDictionary、NSSet ... 之類的對(duì)象仲翎。
?集合類immutable對(duì)象使用 copy 和 mutableCopy 的一個(gè)例子:
NSArray *array = @[@[@"a", @"b"], @[@"c", @"d"]];
NSArray *copyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];
查看內(nèi)存痹扇,可以看到 copyArray 和 array 的地址是一樣的,而 mCopyArray 和 array 的地址是不同的溯香。說(shuō)明 copy 操作進(jìn)行了指針拷貝鲫构,mutableCopy 進(jìn)行了內(nèi)容拷貝。但需要強(qiáng)調(diào)的是:此處的內(nèi)容拷貝玫坛,僅僅是拷貝 array 這個(gè)對(duì)象结笨,array 集合內(nèi)部的元素仍然是指針拷貝。
mutable 對(duì)象拷貝的例子:
NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];
NSArray *copyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];
查看內(nèi)存湿镀,copyArray炕吸、mCopyArray和 array 的內(nèi)存地址都不一樣赫模,說(shuō)明 copyArray蒸矛、mCopyArray 都對(duì) array 進(jìn)行了內(nèi)容拷貝。同樣斩祭,我們可以得出結(jié)論
在集合類對(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ù)制溺欧。?
[immutableObject copy] // 淺復(fù)制
[immutableObject mutableCopy] //單層深復(fù)制
[mutableObject copy] //單層深復(fù)制
[mutableObject mutableCopy] //單層深復(fù)制