meta class總結(jié):
- 類的實(shí)例對象的 isa 指向它的類;類的 isa 指向該類的 metaclass
- 類的 super_class 指向其父類,如果該類為根類則值為 nil
- metaclass 的 isa 指向根 metaclass,如果該 metaclass 是根 metaclass 則指向自身
-
metaclass 的 super_class 指向父 metaclass,如果該 metaclass 是根 metaclass 則指向該 metaclass 對應(yīng)的類;
如圖所示
super class 和meta class
示例:(來自參考1第二題)
下面的代碼是報(bào)錯、警告、正常輸出?
Father *father = [Father new];
BOOL b1 = [father responseToSelector:@selector(responseToSelector:)];
BOOL b2 = [Father responseToSelector:@selector(responseToSelector:)];
NSLog(@"%d, %d", b1, b2);
答案是正常輸出,均為YES。原因:
- 不論是實(shí)例對象還是 Class,都是 id 類型的對象(Class 也是對象)
- 實(shí)例對象的 isa 指向它的 Class(儲存所有減號方法),Class 對象的 isa 指向元類(儲存所有加號方法)
- 向一個對象(id 類型的對象)發(fā)送消息時,都是從這個對象的 isa 指針指向的 Class 中尋找方法
回到題目,當(dāng)向 Father 類發(fā)送一個實(shí)例方法(- responseToSelector)消息時
- 會從它的 isa ,也就是 Father 元類對象中尋找,由于元類中的方法都是類方法,自然找不到
- 于是沿著繼承鏈去父類 NSObject 的元類中尋找,依然找不到
- 由于 objc 這塊的設(shè)計(jì),Objc 元類的父類是 NSObject 類(也就是我們熟悉的 NSObject 類),其中有所有的實(shí)例方法,因此找到了
- responseToSelector
objc_msgSend工作原理
在Objective-C中,消息直到運(yùn)行時才會綁定到方法的實(shí)現(xiàn)上。編譯器會把代碼中[target doSth]轉(zhuǎn)換成 objc_msgSend消息函數(shù),這個函數(shù)完成了動態(tài)綁定的所有事情。它的運(yùn)行流程如下:
- 檢查selector是否需要忽略。(ps: Mac開發(fā)中開啟GC就會忽略retain,release方法。)
- 檢查target是否為nil。如果為nil,直接cleanup,然后return。(這就是我們可以向nil發(fā)送消息的原因。)
- 然后在target的Class中根據(jù)Selector去找IMP
尋找IMP的過程:
- 先從當(dāng)前class的cache方法列表(cache methodLists)里去找
- 找到了,跳到對應(yīng)函數(shù)實(shí)現(xiàn)
- 沒找到,就從class的方法列表(methodLists)里找
- 還找不到,就到super class的方法列表里找,直到找到基類(NSObject)為止
- 最后再找不到,就會進(jìn)入動態(tài)方法解析和消息轉(zhuǎn)發(fā)的機(jī)制。
Runtime常見應(yīng)用
具體見下面文章
Runtime常見作用舉例
