isa 指針理解整理

Class?數(shù)據(jù)結(jié)構(gòu):

class 結(jié)構(gòu)體(舊結(jié)構(gòu))
最新的 ?object--對象結(jié)構(gòu)體

?getIsa( ) ?為獲取 isa 指向的類,isa 指向的類是對象的真實類型。

objc_object?結(jié)構(gòu)體包含一個?isa?指針,類型為?isa_t?聯(lián)合體。 可表示多種形態(tài),既可以當(dāng)成是指針,也可以存儲標(biāo)志位。


注意: ?isa?指針不總是指向?qū)嵗龑ο笏鶎俚念?,不能依靠它來確定類型,而是應(yīng)該用?class?方法來確定實例對象的類。因為KVO的實現(xiàn)機(jī)理就是將被觀察對象的?isa?指針指向一個中間類而不是真實的類,這是一種叫做isa-swizzling的技術(shù)。

1. Class是一個指向objc_class(類)結(jié)構(gòu)體的指針,而id是一個指向objc_object(對象)結(jié)構(gòu)體的指針。

2. 類結(jié)構(gòu)體 (objc_class)繼承自對象結(jié)構(gòu)體(objc_object),所以類也是對象。isa指針,也是從object結(jié)構(gòu)體繼承來的isa。

class 類結(jié)構(gòu)體-- 新的

isa 指向總結(jié):

1. 對象 (objec_object?)的isa指針, 指向他的類對象。

2.?類對象 (objec_class)的isa 指針, 指向他的元類。

注??:類對象中存放著普通成員變量與對象方法 (“-”開頭的方法),類對象 在編譯期產(chǎn)生用于創(chuàng)建實例對象,是單例。

注??:成員變量是存放在類對象中的,并且編譯的那一刻就已經(jīng)決定好了。而分類是在運(yùn)行時才去加載的。 分類的結(jié)構(gòu)中沒有成員變量列表,因此分類中不可以添加成員變量。

3.?元類(metaclass):也是一個對象,所有的元類的 isa 指針都會指向一個根元類。元類中保存了創(chuàng)建類對象以及類方法所需的所有信息(+ 方法列表 )。

4.?根元類的isa指針又會指向他自己,形成一個閉環(huán)。根元類 super class父類指向NSObject類對象。

5.?每個類僅有一個類對象,而每個類對象僅有一個與之相關(guān)的元類。

6. super_class 指針指向 objc_class 類所繼承的父類,如果當(dāng)前類已經(jīng)是最頂層的類(如NSProxy), 則 super_class 指針為 NULL。

isa指針&父類&元類之間的關(guān)系

對象方法的調(diào)用: 在運(yùn)行時編譯器會將代碼轉(zhuǎn)化為 objc_msgSend(obj, @selector (selector))

1. 首先通過obj(對象)的 isa 指針找到obj(對象)對應(yīng)的class(類)

2. 在class(類)中先去cache 中通過SEL(方法的編號)查找對應(yīng)method(方法)

3. 若cache中未找到,再去methodLists中查找

4. 若methodists中未找到,通過 super_class向上一級父類結(jié)構(gòu)體中查找,直至根class(也就是NSObject), ?找到后 將method(方法)加入到cache中,以方便下次查找?

5. 找到后通過method(方法)中的函數(shù)指針 IMP 跳轉(zhuǎn)到對應(yīng)的函數(shù)中去執(zhí)行。

類方法的調(diào)用:

1. ?通過自己的 isa 指針指向的 objc_class 中的 isa 指針找到元類

2. 從元類的 methodLists 中查找該類方法,找不到則會通過元類 的super_class指針找到父類的元類結(jié)構(gòu)體,然后從methodLists中查找該方法,如果仍然找不到,則繼續(xù)通過super_class向上一級父類結(jié)構(gòu)體中查 找,直至根元類?

3. 找到后通過method(方法)中的函數(shù)指針 IMP 跳轉(zhuǎn)到對應(yīng)的函數(shù)中去執(zhí)行。

objc_cache: 方法緩存列表

找到要執(zhí)行的方法后,把方法 的 method_name 作為key ,method_imp作為value 給存起來。當(dāng)再次收到這個消息的時候,可以直接在cache 里找到,避免去遍 objc_method_list。提高效率。

method_imp: 指向?qū)崿F(xiàn)程序的內(nèi)存地址的指針。

注意:

如果直到 根類還是無法找到對應(yīng)的方法,說明該接收者對象響應(yīng)該消息,那么就會觸發(fā)消息轉(zhuǎn)發(fā)機(jī)制,給開發(fā)者最后一次挽救程序crash的機(jī)會。如果消息轉(zhuǎn)發(fā)都失敗了就回執(zhí)行doesNotRecognizeSelector:方法報unrecognized selector錯。

iSA 日常使用 --- kvo的實現(xiàn)原理:

1. 系統(tǒng)動態(tài)的生成一個類對象,這個類是監(jiān)聽對象的類的子類

2. 在生成的子類中重寫了被監(jiān)聽的屬性的set方法,之后將監(jiān)聽對象的isa指針指向系統(tǒng)動態(tài)生成的這個類

3. 當(dāng)監(jiān)聽對象調(diào)用set方法時,由于監(jiān)聽對象的isa指針指向的是剛剛動態(tài)生成的類,所以執(zhí)行的set方法也是子類中重寫的set方法。

參考:kvo原理傳送門

實現(xiàn)類似于多繼承:通過rutime 修改某個對象isa指針的指向,讓對象調(diào)用一些原本不屬于他的方法。(消息轉(zhuǎn)發(fā))isa--swizzing?


OC的函數(shù),屬于動態(tài)調(diào)用過程,在編譯期并不能決定真正調(diào)用哪個函數(shù),只有在真正運(yùn)行時才會根據(jù)函數(shù)的名稱找到對應(yīng)的函數(shù)來調(diào)用。因此給一個對象發(fā)送消息,并不會立即執(zhí)行。

Objective-C的優(yōu)點是它是動態(tài)的。動態(tài)能力有三種:

動態(tài)類-運(yùn)行時確定類的對象

動態(tài)綁定-運(yùn)行時確定要調(diào)用的方法

動態(tài)加載--運(yùn)行時為程序加載新的模塊:添加分類,方法,屬性等。


參考:

蘋果開發(fā)中文網(wǎng)站 - OC-底層實現(xiàn)isa指針 - CocoaChina_讓移動開發(fā)更簡單

isa指針介紹 - 簡書? ??????? ,變成一個共用體(union)結(jié)構(gòu),用位域來存儲更多的信息

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

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

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