今天大概學(xué)習(xí)了下iOS的消息轉(zhuǎn)發(fā)機(jī)制,還是挺有收獲,在此做下筆記,以便后面溫習(xí)。
1.iOS的消息轉(zhuǎn)發(fā)機(jī)制原理如下圖
從全局來看,消息轉(zhuǎn)發(fā)機(jī)制共分為3大步驟:
1).Method resolution 方法解析處理階段
2).Fast forwarding 快速轉(zhuǎn)發(fā)階段
3).Normal forwarding 常規(guī)轉(zhuǎn)發(fā)階段
那么如果想要不拋出unrecognized selector 的報(bào)錯(cuò),也就需要從這3步里面來做補(bǔ)救了,我們一步一步來看如何在這3個(gè)階段來進(jìn)行補(bǔ)救。
2.消息的轉(zhuǎn)發(fā)攔截
iOS 方法調(diào)用的實(shí)質(zhì)是調(diào)用objc_msgsend(id self, SEL op, ...)方法,objc_msgsend()方法會(huì)去class里面的方法列表去查找相應(yīng)的方法(一般會(huì)先去class的方法緩存去查找,如果緩存查不到,則會(huì)去方法列表查找)。如果在class或者class的繼承鏈中沒有找到對應(yīng)的方法,那么就會(huì)觸發(fā)消息轉(zhuǎn)發(fā)。如果不做任何處理,在代碼運(yùn)行的時(shí)候會(huì)崩潰,出現(xiàn)方法未定義的錯(cuò)誤提示。
3.+ (BOOL)resolveInstanceMethod:(SEL)sel,方法解析處理階段
這是蘋果給開發(fā)者第一次處理未定義消息的機(jī)會(huì)。在這個(gè)方法里面可以利用runtime機(jī)制添加方法,當(dāng)對象在class方法列表里面沒有找到對應(yīng)的方法后,就會(huì)執(zhí)行這個(gè)方法里面的代碼。
4.如果+ (BOOL)resolveInstanceMethod:(SEL)sel返回NO,或者未做任何處理。這時(shí)會(huì)來到- (id)forwardingTargetForSelector:(SEL)aSelector,快速轉(zhuǎn)發(fā)階段。這個(gè)方法是消息接受找一個(gè)替代者,由替代者去執(zhí)行傳過來的方法。
5.如果上面兩步都沒有做任何處理,那么還有第三次機(jī)會(huì),可以對消息進(jìn)行處理。- (void)forwardInvocation:(NSInvocation*)anInvocation,常規(guī)消息轉(zhuǎn)發(fā)。
如果這三步都沒有做任何處理,那么運(yùn)行程序會(huì)導(dǎo)致崩潰發(fā)生,提示方法未定義!!!