iOS深入理解property之getter

前言

一直以來都有去通過blog去了解一下技術(shù)的問題,但是因?yàn)閎log畢竟是別人消化的東西,在作者閱讀相關(guān)資料 -> 消化 -> blog文字輸出 -> 自己讀blog -> 自己消化,這是一個(gè)很長的信息鏈,而這個(gè)鏈接每一個(gè)環(huán)節(jié)都存在信息漏斗,到最終到自己消化的時(shí)候,可能和信息最初的樣子,會(huì)有比較大的偏差了。

還有另外一個(gè)問題就是,讀取別人的blog,自己沒有親身實(shí)踐過,看的時(shí)候理解了,但是總是不深刻,到后面遇到這個(gè)知識點(diǎn)的時(shí)候,需要比較長的時(shí)間去慢慢回憶起來,組合成一個(gè)大概的信息具象,沒有一個(gè)系統(tǒng)的了解。

高中的時(shí)候,數(shù)學(xué)老師一直在強(qiáng)調(diào)好記性不如爛筆頭,一直叫我們就算看懂了,你寫下來之后理解會(huì)加深,現(xiàn)在深有體會(huì)?,F(xiàn)在不是好記性不如爛筆頭,像我這種記性不好的,需要爛鍵盤的??!

所以,在以后的工作還是需要作出一點(diǎn)點(diǎn)改變,看到需要不理解的知識點(diǎn),是需要從信息的根來源進(jìn)行尋根問題,并且記下來用文字表達(dá)一次,才能對相關(guān)知識點(diǎn)有一個(gè)系統(tǒng)行的理解。

吃過的虧,要接受教訓(xùn)??!

所以這篇文章是在理解property,是從runtime和CoreFoundation出發(fā)去理解,理解其原理,能有更深刻的理解。

runtime的getter實(shí)現(xiàn)

在很多書籍或者blog里面,都有解析到Objective-C中各個(gè)修飾屬性的區(qū)別,因?yàn)槎际且粋€(gè)結(jié)論給出,并沒有理解里面的具體實(shí)現(xiàn),所以并不深刻。所以,在runtime層面查看對象屬性賦值的實(shí)現(xiàn)。

在runtime的源代碼中,在Private Header下的objc_abi.h文件中,可以找到對象屬性讀寫的abi定義,而實(shí)際的實(shí)現(xiàn)代碼存放在objc-accessors.mm文件中。由于這是私有abi,在iOS的SDK里面的/usr/include/目錄下并不能看到這些信息。如果需要查看這個(gè)定義,需要在runtime的源代碼才能看到。

在這個(gè)objc-accessors.mm文件中,先看getter方法對應(yīng)的實(shí)現(xiàn):

//getter函數(shù)參數(shù)與定義的修飾詞相關(guān)的就只有atomic修飾詞
//也就是說除了atomic修飾詞和nonatomic修飾詞,copy、assign、strong、weak修飾詞都并無相關(guān)
id objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic) {
    if (offset == 0) {
        return object_getClass(self);
    }

    // Retain release world
    id *slot = (id*) ((char*)self + offset);//計(jì)算屬性所在的指針偏移量
    if (!atomic) return *slot;//如果是非原子性操作,直接返回屬性的對象指針
    //原子性操作,則繼續(xù)執(zhí)行
    
    //獲取屬性鎖,屬性鎖的定義是這樣的
    //PropertyLocks是一個(gè)StripedMap<spinlock_t>類型的全局變量
    //而StripedMap是一個(gè)用數(shù)組來實(shí)現(xiàn)的hashmap,key是指針,value是類型是spinlock_t對象
    //而spinlock_t則是mutex_tt<LOCKDEBUG>的類,而mutex_tt類內(nèi)部是由os_unfair_lock mLock來實(shí)現(xiàn)
    //一言以蔽之,PropertyLocks[slot]目的就是獲取os_unfair_lock對象
    spinlock_t& slotlock = PropertyLocks[slot];
    slotlock.lock();//加鎖
    id value = objc_retain(*slot);//獲取到的對象引用計(jì)數(shù)+1
    slotlock.unlock();//解鎖
    
    // for performance, we (safely) issue the autorelease OUTSIDE of the spinlock.
    //將獲取到的對象注冊到自動(dòng)釋放池中,保證值能一定獲取到,所以是線程安全的
    return objc_autoreleaseReturnValue(value);
}

從函數(shù)名上就很清晰的看出來屬性修飾詞對應(yīng)的方法,而且就是標(biāo)準(zhǔn)的objc中函數(shù)調(diào)用時(shí),使用objc_msgSend函數(shù)進(jìn)行函數(shù)調(diào)用的函數(shù)格式。前面兩個(gè)是隱含參數(shù)id和_cmd,后面是函數(shù)的實(shí)際參數(shù)。

通過上述解析,那么可以總結(jié)一下getter的特性了:

  • getter獲取屬性值,copy、assign、strong、weak修飾詞無相關(guān),只與atomic和nonatomic修飾詞有關(guān)
  • 使用nonatomic修飾詞,獲取到屬性值后立馬返回,效率高
  • 使用atomic修飾的屬性,獲取過程會(huì)有加鎖解鎖過程,會(huì)有性能的損耗
  • 使用atomic修飾的屬性,會(huì)將對象注冊到自動(dòng)釋放池中

這就是runtime環(huán)境中g(shù)etter的是整個(gè)過程,相對于setter來說,比較簡單。

最后的最后

上面的分析是基于屬性賦值的猜測,在objc源代碼的全局并沒有搜索到objc_getProperty函數(shù)的調(diào)用方。在runtime中,所有的函數(shù)調(diào)用都是通過objc_msgSend函數(shù)來進(jìn)行調(diào)用的,通過selector方法選擇器來獲取真正的IMP函數(shù)指針來執(zhí)行最終的實(shí)現(xiàn)。而在objc源代碼中,貌似沒有找到IMP的定義,所以以上的分析都是基于猜測的。

今天終于將iMac降級了,能拋棄objc源代碼的工程,但是寫debug代碼后在objc_getProperty打了斷點(diǎn),發(fā)現(xiàn)并沒有調(diào)用到objc_getProperty函數(shù),這就很困惑了。因?yàn)樵谡{(diào)用Foundation層的setter方法,并沒有具體的賦值實(shí)現(xiàn)的。困惑。。。

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

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

  • 各位親愛的家長 為了幫助孩子對初中和高中做一個(gè)好的銜接,教給孩子學(xué)習(xí)高中內(nèi)容的方法和技巧,目前稻谷教育開...
    稻谷龍閱讀 186評論 0 0
  • 高中的時(shí)候,迷茫,空虛,從根上就是飄著的。爸爸媽媽保護(hù)的很好,以為生活很容易,然后衣來伸手飯來張口,養(yǎng)成了懶毛病。...
    王啊啊啊啊增閱讀 480評論 1 2
  • 看表,六點(diǎn)五十,選修老師再次放了鴿子。 這師傅怕是被妖怪抓走了,開課兩周連面都沒見到。 好脾性的我在座位看了一個(gè)小...
    抓星星的小超閱讀 450評論 1 3
  • 1.蘇月白 前年鎮(zhèn)上來了個(gè)白發(fā)青年,住在里鎮(zhèn)上不遠(yuǎn)的荒屋里!很多人都在議論他,說年紀(jì)輕輕就這...
    白發(fā)月舞閱讀 818評論 0 0
  • 人不一定要跨過沒一座山丘才能說自己是英雄 人不一定要橫跨多少片海域才能說自己有傳奇 人不一定要經(jīng)歷多少的故事才能說...
    嘿你的花閱讀 139評論 0 2

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