Effective Objective-C 2.0 編寫(xiě)高質(zhì)量iOS與OS X代碼的52個(gè)有效方法學(xué)習(xí)筆記

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

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

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

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

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

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

第11條講解了對(duì)象的消息傳遞機(jī)制,并強(qiáng)調(diào)了其重要性。第12條則要講解另外-一個(gè)重
要的問(wèn)題,就是對(duì)象在收到無(wú)法解讀的消息之后會(huì)發(fā)生什么情況。
若想令類(lèi)能理解某條消息,我們必須以程序碼實(shí)現(xiàn)出對(duì)應(yīng)的方法才行。但是,在編譯
期向類(lèi)發(fā)送了其無(wú)法解讀的消息并不會(huì)報(bào)錯(cuò),因?yàn)樵谶\(yùn)行期可以繼續(xù)向類(lèi)中添加方法,所以
編譯器在編譯時(shí)還無(wú)法確知類(lèi)中到底會(huì)不會(huì)有某個(gè)方法實(shí)現(xiàn)。當(dāng)對(duì)象接收到無(wú)法解讀的消息
后,就會(huì)啟動(dòng)“消息轉(zhuǎn)發(fā)”( message forwarding)機(jī)制,程序員可經(jīng)由此過(guò)程告訴對(duì)象應(yīng)該如
何處理未知消息。
你可能早就遇到過(guò)經(jīng)由消息轉(zhuǎn)發(fā)流程所處理的消息了,只是未加留意。如果在控制臺(tái)中
看到下面這種提示信息,那就說(shuō)明你曾向某個(gè)對(duì)象發(fā)送過(guò)一條其無(wú)法解讀的消息,從而啟動(dòng)
了消息轉(zhuǎn)發(fā)機(jī)制,并將此消息轉(zhuǎn)發(fā)給了NSObject 的默認(rèn)實(shí)現(xiàn)。
-[___ NSCFNumber lowercaseString]: unrecognized selector sent to
instance 0x87
*** Terminating app due to uncaught exception
'NSInval idArgumentException', reason:
'-[__ NSCFNumber
lowe rcaseString] ; unrecognized selector sent to instance 0x87 '
上面這段異常信息是由NSObject的“doesNotRecognizeSelector:'
方法所拋出的,此異常表明:消息接收者的類(lèi)型是___ NSCFNumber, 而該接收者無(wú)法理解名為lowercaseString
的選擇子。本例所列舉的這種情況并不奇怪,因?yàn)镹SNumber類(lèi)里本來(lái)就沒(méi)有名為
lowercaseString的方法。控制臺(tái)中看到的那個(gè)__ NSFCNumber 是為了實(shí)現(xiàn)“無(wú)縫橋接”(toll-free
bridging,第49條將會(huì)詳解此技術(shù))而使用的內(nèi)部類(lèi)(intermal class), 配置NSNumber對(duì)象時(shí)
也會(huì)- -并創(chuàng)建此對(duì)象。在本例中,消息轉(zhuǎn)發(fā)過(guò)程以應(yīng)用程序崩潰而告終,不過(guò),開(kāi)發(fā)者在編
寫(xiě)自己的類(lèi)時(shí),可于轉(zhuǎn)發(fā)過(guò)程中設(shè)置掛鉤,用以執(zhí)行預(yù)定的邏輯,而不使應(yīng)用程序崩潰。

第49條:對(duì)自定義其內(nèi)存管理語(yǔ)義的collection使用無(wú)縫橋接
簡(jiǎn)單的無(wú)縫橋接


image.png
QQ截圖20180925133731.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容