【Effective Objective-C 2.0 讀書(shū)筆記】第六條:理解“屬性”這一概念

第六條:理解“屬性”這一概念

“屬性”(property)是Objective-C的一項(xiàng)特性,用于封裝對(duì)象中的數(shù)據(jù)。

Objective-C對(duì)象通常會(huì)把其所需的數(shù)據(jù)保存為各種實(shí)例變量疟羹。實(shí)例變量一般通過(guò)“存取方法”(accessmethod)來(lái)訪(fǎng)問(wèn)搁料。

其中,“獲取方法”(getter)用于讀變量值萌庆。

而,“設(shè)置方法”(setter)用于寫(xiě)入變量值。

我們可以在類(lèi)接口的public區(qū)段聲明一些實(shí)例變量:

例:

@inteface person:NSObject {

@public

NSString *_firstName;

NSString *_lastName;

@private

NSString *_someInternalData;

}

@end

我們?cè)贠bjective-C中很少這么做肮疗。

這種寫(xiě)法的問(wèn)題是:對(duì)象布局在編譯期(compile time)就已經(jīng)固定了。只要碰到訪(fǎng)問(wèn)_firstName變量的代碼扒接,編譯器就把其替換為“偏移量”(offset)伪货,這個(gè)偏移量是“硬編碼”(hardcode),表示該變量距離存放對(duì)象的內(nèi)存區(qū)域的起始地址有多遠(yuǎn)钾怔。

這樣做目前看來(lái)沒(méi)有什么問(wèn)題碱呼,但是如果又加了一個(gè)實(shí)例變量,那就麻煩了宗侦。

如果在firstName前加一個(gè)變量dateOfBirth愚臀,那么原來(lái)指向_firstName的地址偏移量就指向了_dateOfBirth了,就會(huì)讀取到錯(cuò)誤的值矾利。

所以姑裂,如果代碼使用了編譯期計(jì)算出來(lái)的偏移量,那么在修改類(lèi)定義之后必須重新編譯梦皮,否則就會(huì)出錯(cuò)炭分。

例如:某個(gè)代碼庫(kù)中的代碼使用了一份舊的類(lèi)定義。如果和其相鏈接的代碼使用了新的類(lèi)定義剑肯,那么運(yùn)行時(shí)就會(huì)出現(xiàn)不兼容現(xiàn)象捧毛。

Objective-C的做法是,把實(shí)例變量當(dāng)做一種存儲(chǔ)偏移量所用的“特殊變量”(special variable),交由“類(lèi)對(duì)象”(class object)保管呀忧。偏移量會(huì)在運(yùn)行期查找师痕,如果類(lèi)定義變了,那么存儲(chǔ)的偏移量也就變了而账,這樣的話(huà)胰坟,無(wú)論何時(shí)訪(fǎng)問(wèn)實(shí)例變量,總能使用正確的偏移量泞辐。甚至可以在運(yùn)行期向類(lèi)中新增實(shí)例變量笔横,這就是穩(wěn)固的“應(yīng)用程序二進(jìn)制接口”(Application Binary Interface,ABI)咐吼。

屬性還有很多的優(yōu)勢(shì):如果使用了屬性的話(huà)吹缔,那么編譯器就會(huì)自動(dòng)編寫(xiě)訪(fǎng)問(wèn)這些屬性所需的方法,此過(guò)程叫做“自動(dòng)合成”(autosynthesis)锯茄。需要強(qiáng)調(diào)的是厢塘,這個(gè)過(guò)程由編譯器在編譯期執(zhí)行,所以編輯器里看不到這些“合成方法”(synthesized method)的源代碼肌幽。除了生成方法代碼之外晚碾,編譯器還要自動(dòng)向類(lèi)中添加適當(dāng)類(lèi)型的實(shí)例變量,并且在屬性名前面加下劃線(xiàn)喂急,以此作為實(shí)例變量的名字格嘁。

如果你不想讓編譯器自動(dòng)合成存取方法,則可以自己實(shí)現(xiàn)煮岁。如果你只實(shí)現(xiàn)了其中一個(gè)存取方法讥蔽,那么另一個(gè)還是會(huì)由編譯器來(lái)合成。還有一種辦法能阻止編譯器自動(dòng)合成存取方法画机,就是使用@dynamic關(guān)鍵字冶伞,它會(huì)告訴編譯器:不要自動(dòng)創(chuàng)建實(shí)現(xiàn)屬性所用的實(shí)例變量,也不要為其創(chuàng)建存取方法步氏。而且响禽,在編譯訪(fǎng)問(wèn)屬性的代碼時(shí),即使編譯器發(fā)現(xiàn)沒(méi)有定義存取方法荚醒,也不會(huì)報(bào)錯(cuò)芋类,他相信這些方法能在運(yùn)行期找到。

因?yàn)橛行傩圆⒉皇菍?shí)例變量界阁,其數(shù)據(jù)來(lái)自后端數(shù)據(jù)庫(kù)中侯繁。

屬性的特質(zhì)

屬性可以擁有的特質(zhì)分為四類(lèi):

原子性

在默認(rèn)情況下,由編譯器合成的方法會(huì)通過(guò)鎖定機(jī)制確保其原子性泡躯。

如果屬性使用nonatomic特質(zhì)贮竟,則不適用同步鎖丽焊。

讀寫(xiě)權(quán)限

具備“readwrite”特質(zhì)的的屬性擁有“獲取方法”和“設(shè)置方法”

具備“readonly”特質(zhì)的屬性擁有“獲取方法”

內(nèi)存管理語(yǔ)義

屬性用于封裝數(shù)據(jù),而數(shù)據(jù)要有“具體的所有權(quán)語(yǔ)義”

assign:“設(shè)置方法”只會(huì)執(zhí)行對(duì)“純量類(lèi)型”(scalar type咕别,例如CGFloat或NSInterger)的簡(jiǎn)單賦值操作

strong:此特質(zhì)表明了屬性定義了一種“擁有關(guān)系”技健。為這種屬性設(shè)置新值時(shí),會(huì)先保留新值惰拱,并釋放舊值雌贱,然后再將新值設(shè)置上去。

weak:此特質(zhì)表明了屬性定義了一種“非擁有關(guān)系”偿短。為這種屬性設(shè)置新值時(shí)欣孤,設(shè)置方法既不保留新值,也不釋放舊值翔冀。此特質(zhì)類(lèi)似assign导街,然而在屬性所指的對(duì)象被銷(xiāo)毀時(shí),屬性值也會(huì)清空纤子。

copy:此特質(zhì)所表達(dá)的所屬關(guān)系與strong類(lèi)似,然而設(shè)置方法并不保留新值款票,而是將其“copy”控硼。當(dāng)屬性類(lèi)型為NSString *時(shí),經(jīng)常用此特質(zhì)來(lái)保護(hù)其封裝性艾少,保護(hù)數(shù)據(jù)不會(huì)在對(duì)象不知情的情況下被修改卡乾。

unsafe_unretained:此特質(zhì)的語(yǔ)義和assign相同,但是它適用于“對(duì)象類(lèi)型”缚够,該特質(zhì)表達(dá)一種“非擁有關(guān)系”幔妨,當(dāng)目標(biāo)對(duì)象被銷(xiāo)毀時(shí),屬性值不會(huì)自動(dòng)清空(“不安全”谍椅,unsafe)误堡,這一點(diǎn)與weak不同。

atomic與nonatomic的區(qū)別是什么呢雏吭?

具備atomic特質(zhì)的獲取方法會(huì)通過(guò)鎖定機(jī)制來(lái)確保其操作的原子性锁施,這在多線(xiàn)程中,總會(huì)使用到有效的屬性值杖们。

但是悉抵,在iOS開(kāi)發(fā)中,摘完,你會(huì)發(fā)現(xiàn)姥饰,其中所有的屬性都聲明為nonatomic。這樣做的歷史原因是:在iOS中使用同步鎖的開(kāi)銷(xiāo)較大孝治,這回帶來(lái)性能問(wèn)題列粪。一般情況下并不要求屬性必須是“原子的”审磁,因?yàn)檫@并不能保證“線(xiàn)程安全”(thread safe),若要實(shí)現(xiàn)線(xiàn)程安全的操作還要更深層次的鎖機(jī)制才行篱竭。

例如:一個(gè)線(xiàn)程在連續(xù)多次讀取某屬性值的過(guò)程中有別的線(xiàn)程在同時(shí)改寫(xiě)該值力图,那么即便將屬性聲明為atomic,也還是會(huì)讀到不同的屬性值掺逼,因此在iOS開(kāi)發(fā)中吃媒,一般都會(huì)使用nonatomic特質(zhì)。

要點(diǎn):

1.可以用@property語(yǔ)法來(lái)定義對(duì)象中所封裝的數(shù)據(jù)

2.通過(guò)“特質(zhì)”來(lái)指定存儲(chǔ)數(shù)據(jù)所需的正確語(yǔ)義

3.在設(shè)置屬性所對(duì)應(yīng)的實(shí)例變量時(shí)吕喘,一定要遵從該屬性值所聲明的語(yǔ)義

4.開(kāi)發(fā)iOS程序時(shí)應(yīng)該使用nonatomic屬性赘那,因?yàn)閍tomic會(huì)嚴(yán)重影響性能

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市氯质,隨后出現(xiàn)的幾起案子募舟,更是在濱河造成了極大的恐慌,老刑警劉巖闻察,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拱礁,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡辕漂,警方通過(guò)查閱死者的電腦和手機(jī)呢灶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)钉嘹,“玉大人鸯乃,你說(shuō)我怎么就攤上這事“匣粒” “怎么了缨睡?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)陈辱。 經(jīng)常有香客問(wèn)我奖年,道長(zhǎng),這世上最難降的妖魔是什么性置? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任拾并,我火速辦了婚禮,結(jié)果婚禮上鹏浅,老公的妹妹穿的比我還像新娘嗅义。我一直安慰自己,他們只是感情好隐砸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布之碗。 她就那樣靜靜地躺著,像睡著了一般季希。 火紅的嫁衣襯著肌膚如雪褪那。 梳的紋絲不亂的頭發(fā)上幽纷,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音博敬,去河邊找鬼友浸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛偏窝,可吹牛的內(nèi)容都是我干的收恢。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼祭往,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼伦意!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起硼补,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤驮肉,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后已骇,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體离钝,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年褪储,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了奈辰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡乱豆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吊趾,到底是詐尸還是另有隱情宛裕,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布论泛,位于F島的核電站揩尸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏屁奏。R本人自食惡果不足惜岩榆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望坟瓢。 院中可真熱鬧勇边,春花似錦、人聲如沸折联。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)诚镰。三九已至奕坟,卻和暖如春祥款,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背月杉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工刃跛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人苛萎。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓桨昙,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親首懈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子绊率,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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