屬性特質(zhì)

? 使用屬性時(shí)還有一個(gè)問題要注意,就是其各種特質(zhì)設(shè)定也會(huì)影響編譯器所生成的存取方法,屬性可以擁有的特質(zhì)分為四類:


原子性:

在默認(rèn)情況下,由編譯器所合成的方法會(huì)通過鎖定機(jī)制確保其原子性(atomicity)。如果屬性具備nonatomic特質(zhì),則不適用同步鎖。請(qǐng)注意,盡管沒有名為"atomic"的特質(zhì)(如果某屬性不具備nonatomic特質(zhì),那它就是"原子的"(atomic)),但是仍然可以在屬性特質(zhì)中寫明這一點(diǎn),編譯器不會(huì)報(bào)錯(cuò)。若是自己定義存取方法,那么就應(yīng)該遵從與屬性特質(zhì)相符的原子性。


? 讀/寫權(quán)限:

1.具備readwrite(讀寫)特質(zhì)的屬性擁有“獲取方法“(getter)與”設(shè)置方法“(setter)。若該屬性由@synthesize實(shí)現(xiàn),則編譯器會(huì)自動(dòng)生成這兩個(gè)方法。

2.具備readonly(只讀)特質(zhì)的屬性僅擁有獲取方法,只有當(dāng)該屬性@synthesize實(shí)現(xiàn)時(shí),編譯器才會(huì)為其合成獲取方法。你可以用此特質(zhì)把某個(gè)屬性對(duì)外公開為只讀屬性。


內(nèi)存管理語義:

屬性用于

封裝數(shù)據(jù),而數(shù)據(jù)則要有”具體的所有權(quán)語義“。下面這一組特質(zhì)僅會(huì)影響”設(shè)置犯非法”。例如,用“設(shè)置方法”設(shè)定一個(gè)新值時(shí),它是應(yīng)該“保留”(retain)此值呢,還是只將其賦值給底層實(shí)例變量就好?編譯器在合成存取方法時(shí),要根據(jù)此特質(zhì)來決定所生成的代碼。如果自己編寫存取方法,那么就必須同有關(guān)屬性所具備的特質(zhì)相符。

1. assign 設(shè)置方法,只會(huì)執(zhí)行針對(duì)“純量類型”(例如CGFloat 或 NSInteger等)的簡單賦值操作。

2. Strong 此特質(zhì)表明該屬性定義了一種“擁有關(guān)系”。為這種屬性設(shè)置新值時(shí),設(shè)置方法會(huì)先保留新值,并釋放舊值,然后再將新值設(shè)置上去。

3. weak 此特質(zhì)表明該屬性定義了一種“非擁有關(guān)系”。為這種屬性設(shè)置新值時(shí),設(shè)置方法既不保留新值,也不釋放舊值。此特質(zhì)同assign類似,然而在屬性所指的對(duì)象遭到摧毀時(shí),屬性值也會(huì)清空。

4. unsafe_unretained 此特質(zhì)的語義和assign相同,但是它適用于“對(duì)象類型”,該特質(zhì)表達(dá)一種“非擁有關(guān)系”("不保留",unretained),當(dāng)目標(biāo)對(duì)象遭到摧毀時(shí),屬性值不會(huì)自動(dòng)清空("不安全",unsafe),這一點(diǎn)與weak有區(qū)別。

5. copy 此特質(zhì)所表達(dá)的屬性關(guān)系與strong類似。然而設(shè)置方法并不保留新值,而是將其“拷貝”(copy)。當(dāng)屬性類型為NSString *時(shí),經(jīng)常用此特質(zhì)來保護(hù)其封裝性,因?yàn)閭鬟f給設(shè)置方法的新值有可能指向一個(gè)NSMutableString類的實(shí)例。這個(gè)類是NSString的子類,表示一種可以修改其值的字符串,此時(shí)若是不拷貝字符串,那么設(shè)置完屬性之后,字符串的值就可能會(huì)在對(duì)象不知情的情況下遭人更改。所以,這時(shí)就要拷貝一份“不可變”(immutable)的字符串,確保對(duì)象中的字符串值不會(huì)無意間變換。只要實(shí)現(xiàn)屬性所用的對(duì)象是“可變的”(mutable),就應(yīng)該在設(shè)置新屬性值時(shí)拷貝一份。


注意:

atomic與nonatomic的區(qū)別是什么呢?具備atomic特質(zhì)的獲取方法會(huì)通過鎖定機(jī)制來確保其操作的原子性。這也就是說,如果兩個(gè)線程讀寫同一屬性,那么不論何時(shí),總能看到有效的屬性值。若是不加鎖的話(或者說使用nonatomic語義),那么當(dāng)其中一個(gè)線程正在改寫某屬性值時(shí),另外一個(gè)線程也許會(huì)突然闖入,把尚未修改好的屬性值讀取出來。發(fā)生這種情況時(shí),線程讀到的屬性值可能不對(duì)。

如果開發(fā)過iOS程序,你就會(huì)發(fā)現(xiàn),其中所有屬性都聲明為nonatomic。這樣做的歷史原因是:在iOS中使用同步鎖的開銷較大,就會(huì)帶來性能問題。一般情況喜愛并不要求屬性必須是“原子的”,因?yàn)檫@并不能保證“線程安全”,若要實(shí)現(xiàn)“線程安全”的操作,還需采用更為深層的鎖定機(jī)制才行。例如,一個(gè)線程在連續(xù)多次讀取某屬性值的過程中有別的線程在同時(shí)改寫該值,那么即便將屬性聲明為atomic,也還是會(huì)讀到不同的屬性值。因此,開發(fā)iOS程序時(shí)一般都會(huì)使用nonatomic屬性。但是在開發(fā)Mac OSX

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容