Runtime
一、數(shù)據(jù)結(jié)構(gòu)
1凡人、objc_object
id = objc_object : isa_t為共用體
2撒会、objc_class
Class = objc_class: Class也是對(duì)象,稱之為類對(duì)象紧卒,因?yàn)樗^承自onjc_object
3奸腺、isa_t
有兩種類型餐禁,指針型isa、非指針型isa
4突照、cach_t
5帮非、class_data_bits_t
6、class_rw_t
例如分類1中添加的方法會(huì)在methods二維數(shù)組中的某個(gè)數(shù)組中存儲(chǔ)
7讹蘑、class_ro_t
name:類名末盔,可以通過(guò)NSClassFromString(name)獲取該類
ivars:成員變量
properties:屬性
8、method_t
Const char* types: 函數(shù)的返回和參數(shù)的組合
9座慰、Type Encodings
第一個(gè)參數(shù)@代表一個(gè)對(duì)象陨舱,第一個(gè)參數(shù)和第二個(gè)參數(shù)是固定的,@代表的是誰(shuí)調(diào)用的版仔,也就是self游盲,第二個(gè):表達(dá)的是方法選擇器
10、對(duì)象邦尊、類對(duì)象背桐、元類對(duì)象
Root class指的就是NSObject
如果一個(gè)實(shí)例方法在元類對(duì)象以及根元類對(duì)象中都沒(méi)有件缸,會(huì)查找根類對(duì)象中的同名實(shí)例方法瓶堕,并調(diào)用图仓。
問(wèn)題
[self class];
[super class];
二励幼、消息傳遞
1跳芳、緩存查找
哈希查找
2洲脂、在類對(duì)象中查找
3杖刷、父類逐級(jí)查找
4励饵、消息轉(zhuǎn)發(fā)
a、動(dòng)態(tài)解析
我們可以根據(jù)方法類型(實(shí)例方法or類方法)重寫(xiě)一下方法滑燃,為類動(dòng)態(tài)添加方法
+(BOOL)resolveInstanceMethod:(SEL)sel
+(BOOL)resolveClassMethod:(SEL)sel
在方法中調(diào)用一下方法來(lái)動(dòng)態(tài)添加方法的實(shí)現(xiàn)
** 參數(shù)1:給哪個(gè)類添加
** 參數(shù)2:給哪個(gè)方法添加
** 參數(shù)3:方法的實(shí)現(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ā)給一個(gè)其他的OC對(duì)象(找一個(gè)備用接收者)
重寫(xiě)以下方法,返回一個(gè)其他對(duì)象即可
+/- (id)forwardingTargetForSelector:(SEL)aSelector
2> Normal forwarding : 實(shí)現(xiàn)一個(gè)完整的消息轉(zhuǎn)發(fā)過(guò)程
如果Fast forwarding沒(méi)有解決可以重寫(xiě)以下兩個(gè)方法啟動(dòng)完整的消息的轉(zhuǎn)發(fā)
+/- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
Runtime 會(huì)根據(jù)這個(gè)方法簽名,創(chuàng)建一個(gè)NSInvocation對(duì)象(NSInvocation封裝了未知消息的全部?jī)?nèi)容表窘,
包括:方法調(diào)用者 target典予、方法名 selector、方法參數(shù) argument 等)乐严,
然后調(diào)用第二個(gè)方法并將該NSInvocation對(duì)象作為參數(shù)傳入瘤袖。
+/- (void)forwardInvocation:(NSInvocation *)invocation
在該方法中:將未知消息轉(zhuǎn)發(fā)給其它對(duì)象;改變未知消息的內(nèi)容(如方法名昂验、方法參數(shù))再轉(zhuǎn)發(fā)給其它對(duì)象捂敌;甚至可以定義任何邏輯艾扮。
??如果第一個(gè)方法中沒(méi)有返回方法簽名,或者我們沒(méi)有重寫(xiě)第二個(gè)方法占婉,系統(tǒng)就會(huì)認(rèn)為我們徹底不想處理這個(gè)消息了泡嘴,
這時(shí)候就會(huì)調(diào)用以下方法
+/- (void)doesNotRecognizeSelector:(SEL)sel
方法并拋出經(jīng)典的 crash:unrecognized selector sent to instance/class,結(jié)束 objc_msgSend 的全部流程锐涯。