ios 消息轉(zhuǎn)發(fā)

ios在類中,沒有定義的函數(shù),要走消息轉(zhuǎn)發(fā)流程。如果不走消息轉(zhuǎn)發(fā)流程,程序會(huì)奔潰。消息轉(zhuǎn)發(fā)流程分四步調(diào)用。

第一步:+ (BOOL)resolveInstanceMethod:(SEL)sel,這個(gè)方法會(huì)調(diào)用,如果在這個(gè)方法中使用

runtime中的class_addMethod這個(gè)方法,可以將沒有定義的方法,進(jìn)行動(dòng)態(tài)增加。

例如:下面的person類

@interface Person : NSObject

- (void)createPerson:(NSString*)str;

@end

@implementation Person

+ (BOOL)resolveInstanceMethod:(SEL)sel{

NSLog(@"%@",NSStringFromSelector(sel));

? ? if(sel ==@selector(createPerson:)) {

? ? ? ? class_addMethod(self, sel,(IMP) newInterRun, "v@:@:");

? ? ? return YES;

}

? ? return [super resolveInstanceMethod:sel];

}

void newInterRun(id self,SEL sel,NSString str) {

? ? NSLog(@"---newInterRun---%@",str);

}

如果在resolveInstanceMethod方法中,增加了方法,消息轉(zhuǎn)發(fā)流程就結(jié)束了。

如果在resolveInstanceMethod方法中,沒有增加方法,直接[super resolveInstanceMethod:sel];,就轉(zhuǎn)發(fā)到第二步。

第二步:- (id)forwardingTargetForSelector:(SEL)aSelector,這個(gè)方法是消息轉(zhuǎn)發(fā)其他類中定義當(dāng)前aSelector的方法,

例如:其他類SubPerson

@interfaceSubPerson :NSObject

- (void)createPerson:(NSString*)str;

@end

@implementation SubPerson

- (void)createPerson:(NSString*)str{

? ? NSLog(@"---createPerson---%@",str);

}

@end

- (id)forwardingTargetForSelector:(SEL)aSelector{

? ? NSLog(@"%@",NSStringFromSelector(aSelector));

? ? return [SubPerson new];

}

如果在forwardingTargetForSelector方法中明確轉(zhuǎn)發(fā)特定的類時(shí),此時(shí)消息轉(zhuǎn)發(fā)結(jié)束;

如果在forwardingTargetForSelector方法中沒有明確轉(zhuǎn)特定的類是,此時(shí)要繼續(xù)轉(zhuǎn)發(fā)和重新簽名,然后進(jìn)入第三步

- (id)forwardingTargetForSelector:(SEL)aSelector{

? ? NSLog(@"%@",NSStringFromSelector(aSelector));

? ? return [super forwardingTargetForSelector:aSelector];

}

- (NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector{

? ? if(aSelector ==@selector(createPerson:)) {

? ? ? ? NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:"v@:@:"];

? ? ? ? returnsignature;

? ? }

? ? else{

?? ? ? return [super methodSignatureForSelector:aSelector];

? ? }

}

如果不簽名,直接調(diào)用[super methodSignatureForSelector:aSelector];,導(dǎo)致整個(gè)流程會(huì)崩潰的。

第三步:- (void)forwardInvocation:(NSInvocation*)anInvocation,這個(gè)方法是最后特定類的方法進(jìn)行調(diào)用

- (void)forwardInvocation:(NSInvocation*)anInvocation{

? ? NSLog(@"%@",anInvocation);

? ? SEL sel = anInvocation.selector;

? ? SubPerson *p = [SubPerson new];

? ? if ([p respondsToSelector:sel]) {

? ? ? ? [anInvocation invokeWithTarget:p];

? ? }

? ? else{

? ? ? ? [superforwardInvocation:anInvocation];

? ? }

}

如果在SubPerson類中定義sel,轉(zhuǎn)發(fā)流程結(jié)束。

如果在SubPerson類中沒有定義sel,轉(zhuǎn)發(fā)到第四步。

第四步:- (void)doesNotRecognizeSelector:(SEL)aSelector,調(diào)用這個(gè)方法,進(jìn)行提示,當(dāng)前aSelector,在整個(gè)消息轉(zhuǎn)發(fā)流程中,都沒有定義這個(gè),然后進(jìn)行提示。

- (void)doesNotRecognizeSelector:(SEL)aSelector{

? ? NSLog(@"%@",NSStringFromSelector(aSelector));

? ?//增加提示

}

以上是消息轉(zhuǎn)發(fā)的整個(gè)流程。? ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 消息轉(zhuǎn)發(fā)機(jī)制 假設(shè)說我們聲明一個(gè)類, 初始化對(duì)象, 并且在此類聲明一個(gè)方法, 調(diào)用方法的時(shí)候底層是怎么處理的呢? ...
    軟件iOS開發(fā)閱讀 345評(píng)論 0 0
  • 以前知道蘋果執(zhí)行方法是通過消息執(zhí)行的,當(dāng)對(duì)應(yīng)的對(duì)象或者類無法處理該消息時(shí),蘋果就會(huì)啟動(dòng)消息轉(zhuǎn)發(fā)機(jī)制,通過這一機(jī)制,...
    海浪萌物閱讀 543評(píng)論 0 0
  • 1、動(dòng)態(tài)方法解析 對(duì)象在收到無法處理的消息時(shí),會(huì)調(diào)用下面的方法,前者是調(diào)用類方法時(shí)會(huì)調(diào)用,后者是調(diào)用對(duì)象方法時(shí)會(huì)調(diào)...
    Colin_狂奔的螞蟻閱讀 486評(píng)論 1 3
  • OC具有動(dòng)態(tài)語言特性,盡管OC基于C語言,這一點(diǎn)也是與C語言最大的區(qū)別之一。C語言在編譯的時(shí)候就決定了要調(diào)用的...
    jiangamh閱讀 783評(píng)論 2 4
  • OC消息轉(zhuǎn)發(fā) oc中的調(diào)用對(duì)象或者類不存在的方法,會(huì)執(zhí)行一遍消息轉(zhuǎn)發(fā)流程.消息轉(zhuǎn)發(fā)主要包括4步 首先調(diào)用+ (BO...
    nullyy閱讀 447評(píng)論 0 0

友情鏈接更多精彩內(nèi)容