這篇文章,我們主要來介紹一下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.多維陣列也是...