Runtime
一、數(shù)據(jù)結(jié)構(gòu)

1、objc_object
id = objc_object : isa_t為共用體

2、objc_class
Class = objc_class: Class也是對象,稱之為類對象,因為它繼承自onjc_object

3、isa_t
有兩種類型,指針型isa、非指針型isa


4、cach_t


5、class_data_bits_t

6、class_rw_t
例如分類1中添加的方法會在methods二維數(shù)組中的某個數(shù)組中存儲

7、class_ro_t
name:類名,可以通過NSClassFromString(name)獲取該類
ivars:成員變量
properties:屬性

8、method_t
Const char* types: 函數(shù)的返回和參數(shù)的組合

9、Type Encodings
第一個參數(shù)@代表一個對象,第一個參數(shù)和第二個參數(shù)是固定的,@代表的是誰調(diào)用的,也就是self,第二個:表達(dá)的是方法選擇器

10、對象、類對象、元類對象

Root class指的就是NSObject
如果一個實例方法在元類對象以及根元類對象中都沒有,會查找根類對象中的同名實例方法,并調(diào)用。

問題
[self class];
[super class];


二、消息傳遞

1、緩存查找
哈希查找

2、在類對象中查找

3、父類逐級查找

4、消息轉(zhuǎn)發(fā)

a、動態(tài)解析
我們可以根據(jù)方法類型(實例方法or類方法)重寫一下方法,為類動態(tài)添加方法
+(BOOL)resolveInstanceMethod:(SEL)sel
+(BOOL)resolveClassMethod:(SEL)sel
在方法中調(diào)用一下方法來動態(tài)添加方法的實現(xiàn)
** 參數(shù)1:給哪個類添加
** 參數(shù)2:給哪個方法添加
** 參數(shù)3:方法的實現(xiàn)地址
** 參數(shù)4:方法的編碼類型
BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)


b、消息轉(zhuǎn)發(fā)
消息轉(zhuǎn)發(fā)分為兩步進(jìn)行: Fast forwarding和 Normal forwarding
1> Fast forwarding : 將消息轉(zhuǎn)發(fā)給一個其他的OC對象(找一個備用接收者)
重寫以下方法,返回一個其他對象即可
+/- (id)forwardingTargetForSelector:(SEL)aSelector

2> Normal forwarding : 實現(xiàn)一個完整的消息轉(zhuǎn)發(fā)過程
如果Fast forwarding沒有解決可以重寫以下兩個方法啟動完整的消息的轉(zhuǎn)發(fā)
+/- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
Runtime 會根據(jù)這個方法簽名,創(chuàng)建一個NSInvocation對象(NSInvocation封裝了未知消息的全部內(nèi)容,
包括:方法調(diào)用者 target、方法名 selector、方法參數(shù) argument 等),
然后調(diào)用第二個方法并將該NSInvocation對象作為參數(shù)傳入。
+/- (void)forwardInvocation:(NSInvocation *)invocation
在該方法中:將未知消息轉(zhuǎn)發(fā)給其它對象;改變未知消息的內(nèi)容(如方法名、方法參數(shù))再轉(zhuǎn)發(fā)給其它對象;甚至可以定義任何邏輯。

??如果第一個方法中沒有返回方法簽名,或者我們沒有重寫第二個方法,系統(tǒng)就會認(rèn)為我們徹底不想處理這個消息了,
這時候就會調(diào)用以下方法
+/- (void)doesNotRecognizeSelector:(SEL)sel
方法并拋出經(jīng)典的 crash:unrecognized selector sent to instance/class,結(jié)束 objc_msgSend 的全部流程。