? 使用屬性時(shí)還有一個(gè)問題要注意基协,就是其各種特質(zhì)設(shè)定也會影響編譯器所生成的存取方法,屬性可以擁有的特質(zhì)分為四類:
原子性:
在默認(rèn)情況下,由編譯器所合成的方法會通過鎖定機(jī)制確保其原子性(atomicity)牡直。如果屬性具備nonatomic特質(zhì),則不適用同步鎖纳决。請注意碰逸,盡管沒有名為"atomic"的特質(zhì)(如果某屬性不具備nonatomic特質(zhì),那它就是"原子的"(atomic))阔加,但是仍然可以在屬性特質(zhì)中寫明這一點(diǎn)饵史,編譯器不會報(bào)錯(cuò)。若是自己定義存取方法掸哑,那么就應(yīng)該遵從與屬性特質(zhì)相符的原子性约急。
? 讀/寫權(quán)限:
1.具備readwrite(讀寫)特質(zhì)的屬性擁有“獲取方法“(getter)與”設(shè)置方法“(setter)。若該屬性由@synthesize實(shí)現(xiàn)苗分,則編譯器會自動生成這兩個(gè)方法。
2.具備readonly(只讀)特質(zhì)的屬性僅擁有獲取方法牵辣,只有當(dāng)該屬性@synthesize實(shí)現(xiàn)時(shí)摔癣,編譯器才會為其合成獲取方法。你可以用此特質(zhì)把某個(gè)屬性對外公開為只讀屬性纬向。
內(nèi)存管理語義:
屬性用于
封裝數(shù)據(jù)择浊,而數(shù)據(jù)則要有”具體的所有權(quán)語義“。下面這一組特質(zhì)僅會影響”設(shè)置犯非法”逾条。例如琢岩,用“設(shè)置方法”設(shè)定一個(gè)新值時(shí),它是應(yīng)該“保留”(retain)此值呢师脂,還是只將其賦值給底層實(shí)例變量就好担孔?編譯器在合成存取方法時(shí)江锨,要根據(jù)此特質(zhì)來決定所生成的代碼。如果自己編寫存取方法糕篇,那么就必須同有關(guān)屬性所具備的特質(zhì)相符啄育。
1. assign 設(shè)置方法,只會執(zhí)行針對“純量類型”(例如CGFloat 或 NSInteger等)的簡單賦值操作拌消。
2. Strong 此特質(zhì)表明該屬性定義了一種“擁有關(guān)系”挑豌。為這種屬性設(shè)置新值時(shí),設(shè)置方法會先保留新值墩崩,并釋放舊值氓英,然后再將新值設(shè)置上去。
3. weak 此特質(zhì)表明該屬性定義了一種“非擁有關(guān)系”鹦筹。為這種屬性設(shè)置新值時(shí)铝阐,設(shè)置方法既不保留新值,也不釋放舊值盛龄。此特質(zhì)同assign類似饰迹,然而在屬性所指的對象遭到摧毀時(shí),屬性值也會清空余舶。
4. unsafe_unretained 此特質(zhì)的語義和assign相同啊鸭,但是它適用于“對象類型”,該特質(zhì)表達(dá)一種“非擁有關(guān)系”("不保留"匿值,unretained)赠制,當(dāng)目標(biāo)對象遭到摧毀時(shí),屬性值不會自動清空("不安全"挟憔,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è)置完屬性之后搂妻,字符串的值就可能會在對象不知情的情況下遭人更改蒙保。所以,這時(shí)就要拷貝一份“不可變”(immutable)的字符串欲主,確保對象中的字符串值不會無意間變換邓厕。只要實(shí)現(xiàn)屬性所用的對象是“可變的”(mutable)逝嚎,就應(yīng)該在設(shè)置新屬性值時(shí)拷貝一份。
注意:
atomic與nonatomic的區(qū)別是什么呢邑狸?具備atomic特質(zhì)的獲取方法會通過鎖定機(jī)制來確保其操作的原子性懈糯。這也就是說,如果兩個(gè)線程讀寫同一屬性单雾,那么不論何時(shí)赚哗,總能看到有效的屬性值。若是不加鎖的話(或者說使用nonatomic語義)硅堆,那么當(dāng)其中一個(gè)線程正在改寫某屬性值時(shí)屿储,另外一個(gè)線程也許會突然闖入,把尚未修改好的屬性值讀取出來渐逃。發(fā)生這種情況時(shí)够掠,線程讀到的屬性值可能不對。
如果開發(fā)過iOS程序茄菊,你就會發(fā)現(xiàn)疯潭,其中所有屬性都聲明為nonatomic。這樣做的歷史原因是:在iOS中使用同步鎖的開銷較大面殖,就會帶來性能問題竖哩。一般情況喜愛并不要求屬性必須是“原子的”,因?yàn)檫@并不能保證“線程安全”脊僚,若要實(shí)現(xiàn)“線程安全”的操作相叁,還需采用更為深層的鎖定機(jī)制才行。例如辽幌,一個(gè)線程在連續(xù)多次讀取某屬性值的過程中有別的線程在同時(shí)改寫該值增淹,那么即便將屬性聲明為atomic,也還是會讀到不同的屬性值乌企。因此虑润,開發(fā)iOS程序時(shí)一般都會使用nonatomic屬性。但是在開發(fā)Mac OSX