消息轉(zhuǎn)發(fā)機(jī)制分為三步:
一软棺、動(dòng)態(tài)方法解析
二红竭、快速消息轉(zhuǎn)發(fā)
三、標(biāo)準(zhǔn)消息轉(zhuǎn)發(fā)(normal forwarding)
參考文章:https://blog.csdn.net/qq_31586759/article/details/95081089
一喘落、動(dòng)態(tài)方法解析
1.執(zhí)行方法調(diào)用代碼(實(shí)例對象調(diào)用實(shí)例方法茵宪,類對象調(diào)用類方法)
Person *person = [[Person alloc] init];
[person eat];
2.查詢對象中是否存在對應(yīng)方法的IMP指針(實(shí)例方法在類里面找,類方法在父類中找)
3.如果存在瘦棋,則直接執(zhí)行IMP
指針對應(yīng)的方法稀火,方法調(diào)用結(jié)束。如果不存在赌朋,則執(zhí)行4
4.判斷該調(diào)用對象有沒有實(shí)現(xiàn)resolveInstanceMethod:
(調(diào)用實(shí)例方法時(shí))或者resolveClassMethod:
(調(diào)用類方法時(shí))進(jìn)行動(dòng)態(tài)方法添加凰狞、交換,如果有箕慧,返回YES
服球,執(zhí)行動(dòng)態(tài)添加、交換的方法颠焦。如果沒有斩熊,則調(diào)用[super resolveInstanceMethod:]
或者[super resolveClassMethod:]
,返回NO
時(shí)則繼續(xù)執(zhí)行5
二伐庭、快速消息轉(zhuǎn)發(fā)
5.當(dāng)IMP
指針不存在時(shí)粉渠,尋找是否在其他對象類有該方法實(shí)現(xiàn),并將該消息轉(zhuǎn)發(fā)給這個(gè)對象的forwardingTargetForSelector:
方法,如果目標(biāo)對象實(shí)現(xiàn)了該方法,runtime
這時(shí)就會(huì)調(diào)用這個(gè)方法,給你把這個(gè)消息轉(zhuǎn)發(fā)給其他對象的機(jī)會(huì).只要這個(gè)方法返回的不是nil
和self
,整個(gè)消息發(fā)送的過程就會(huì)被重啟,當(dāng)然返回的對象會(huì)變成return的對象,否則就會(huì)繼續(xù)標(biāo)準(zhǔn)消息轉(zhuǎn)發(fā)(normal forwarding)
三圾另、標(biāo)準(zhǔn)消息轉(zhuǎn)發(fā)(normal forwarding)
這一步是消息轉(zhuǎn)發(fā)機(jī)制中最后一道屏障霸株,,首先會(huì)發(fā)送- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
消息獲得函數(shù)的參數(shù)和返回值,如果返回nil
,runtime
則會(huì)發(fā)出doesNotRecognizeSelector:
消息,然后crash
,若是返回了一個(gè)函數(shù)簽名,runtime
就會(huì)創(chuàng)建一個(gè)NSInvocation
對象并發(fā)送- (void)forwardInvocation:(NSInvocation *)Invocation
消息給目標(biāo)對象。