Runtime的本質 二

2021-10-06 08:04:49 字數 3028 閱讀 5887

這篇文章,我們主要來介紹一下objc_class結構的內容與含義。

我們知道class的型別是objc_class型別

typedef struct objc_class *class;

點進去objc_class可以看到部分定義:

objc_object的部分定義:

其中:class_rw_t中的rw是read和write的意思,也就是class_rw_t裡面的內容是可讀可寫的。

class_ro_t中的ro是read和only read的意思,也就是class_ro_t裡面的內容是唯讀的。

通過ios大神mj老師寫的檔案mjclassinfo.h,我們可以窺探class的具體內容。

匯入檔案,注意,add to targets不要選中

好強大的工具,給mj點讚

在class_rw_t儲存的方法列表、屬性列表、協議列表都是二維陣列。以方法列表為例:

method_array_t裡面是method_list_t;method_list_t裡面是結構體method_t

struct method_t };

};

在原始碼中可以看出:

而class_ro_t裡面也有方法列表

參考原始碼,可以得出:

原始的class_ro_t中的方法列表與分類中的方法列表結合,放到class_rw_t的方法列表中。

這是個大佬

method_t是對方法/函式的封裝。

通過檢視原始碼,可以看到method_t結構的組成:

struct method_t 

;

其中,imp代表函式的具體實現,imp是指向函式位址的指標,通過imp可以真正的找到函式的入口。

sel代表方法/函式名,一般叫做選擇器,底層結構跟char *類似。

可以通過@selector()sel_registername()獲得

可以通過sel_getname()nsstringfromselector()轉成字串

不同類中相同名字的方法,所對應的方法選擇器是相同的

types是乙個包含了函式的返回值型別、引數型別的編碼字串

其屬於type encoding型別編碼

ios提供了乙個叫做@encode的指令,可以將具體的型別表示成字串編碼。

對應含義可以在官方文件檢視,這裡僅列出一部分:

我們需要了解的是:

可以通過method_t裡面的types獲取到函式的返回值型別以及引數型別。

方法快取

在objc_class裡面有乙個cache_t型別的cache,用雜湊表來快取曾經呼叫過的方法,可以提高方法的查詢速度。

其中,cache_t的組成為:

struct cache_t 

struct bucket_t

;

可以看出,用方法名作為key,找函式記憶體位址,形成乙個雜湊表。

舉個具體例子分析:

yzperson *person =

[[yzperson alloc] init]

;[person run]

;

方法快取過程:

第一次呼叫某個物件方法的時候,會去該類的類物件cache中通過key-value方法查詢,key是方法名,查詢對應的imp。

如果查詢不到,會通過isa指標去其類物件裡面查詢該方法,有的話就通過雜湊表快取到cache中並且呼叫該方法。

如果該類物件裡面沒有該方法,則去其父類裡面找,也是先去快取列表中找,找到就放入到自己的快取中並呼叫。快取中沒有則去方法列表中找,找到會通過雜湊表快取到自己cache中並且呼叫,沒找到會繼續去父類中找,直到找不到。第二次呼叫,去cache中查詢,有,直接呼叫,沒有繼續按上面的方法做。

文字敘述有點複雜,不太懂?有沒有圖?

IOS高階開發 Runtime(二)

6 獲取乙個類的所有方法 u int count method methods class copymethodlist customclass class count for int i 0 i count i 設定全域性變數的值 void setinstancevar 9 判斷類的某個屬性的型別...

線性代數的本質(二)

2 原點保持固定。總的來說,你應該把線性變換看作是 保持網格線平行且等距分布 的變換。總之,線性變換是操控空間的一種手段,它保持網格線平行且等距,並且保持原點不動。令人高興的是,這種變換僅用幾個數字就可以描述,這些數字就是變換後基向量的座標。以這些座標為列所構成的矩陣為我們提供了一種描述線性變換的語...

本質啊本質之四 陣列的本質

陣列 1.陣列是同型別的聚合 2.定義乙個陣列,如 type x n 意思是記憶體裡有 n個連續的 type 型變數,連續的排列在一起。x 是第乙個元素的位址,是乙個立即數,是右值,不是變數。x x 0 這是編譯器處理的,因為當你將 x 賦值給乙個指標時 編譯器實際上就用的 x 0 3.多維陣列也是...