iOS的消息转发机制

OC由于运行时特性,可以在运行期间动态添加方法,这个寻找动态添加的方法的过程就是动态消息转发。
iOS的消息转发机制分为三个步骤:动态方法解析、快速消息转发机制、标准消息转发机制
在这里插入图片描述

(一)动态方法解析
首先是征询接收者所属的类,看其是否能动态添加调用的方法,来处理当前这个未知的选择子;

-(BOOL)resolveInstanceMethod:(SEL)selector或者+(BOOL)resolveClassMethod:(SEL)selector;让开发者有机会提供一个函数实现;若返回YES,说明已提供实现,那运行时系统就会重新启动一次消息发送的过程若为NO,则进入消息转发阶段-快速消息转发

void dynamicMethodIMP(id self, SEL _cmd) {  
    NSLog(@" >> dynamicMethodIMP");  
}  
  
+ (BOOL)resolveInstanceMethod:(SEL)selector  
{     
    NSLog(@" >> Instance resolving %@", NSStringFromSelector(selector));  
      
    if (name == @selector(MissMethod)) {  
        class_addMethod([self class], selector, (IMP)dynamicMethodIMP, "v@:");  
        return YES;  
    }  
      
    return [super resolveInstanceMethod:name];  
}  

(二)快速消息转发
寻找是否在其他对象内有该方法实现,并将该消息转发给这个对象-(id)forwardingTargetForSelector:(SEL)selector ,如果目标对象实现了该方法,Runtime这时就会调用这个方法,给你把这个消息转发给其他对象的机会.只要这个方法返回的不是nil和self,整个消息发送的过程就会被重启,当然返回的对象会变成return的对象,否则就会继续nurmal fowarding

- (id)forwardingTargetForSelector:(SEL)aSelector  
{  
    TargetObj *obj = [[TargetObj alloc]init];  
    if ([obj respondsToSelector:aSelector]) {  
        return doctor;  
    }  
    return nil;  
} 

(三)标准消息转发(normal forwarding)
这一步是消息转发的最后一步,首先会发送- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 消息获得函数的参数和返回值,如果返回nil,runtime则会发出doesNotRecognizeSelector消息,然后crash,若是返回了一个函数签名,runtime就会创建一个NSInvocation对象并发送- (void)forwardInvocation:(NSInvocation *)Invocation 消息给目标对象

+ (void)load{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [JaySwizzler swizzleSelector:@selector(methodSignatureForSelector:) onClass:[NSObject class] swizzleTargetSel:@selector(user_methodSignatureForSelector:) classType:NO];
        [JaySwizzler swizzleSelector:@selector(forwardInvocation:) onClass:[NSObject class] swizzleTargetSel:@selector(user_forwardInvocation:) classType:NO];
        
    });
 
}
- (NSMethodSignature *)user_methodSignatureForSelector:(SEL)aSelector{
    
    NSMethodSignature *ms = [self user_methodSignatureForSelector:aSelector];
    if (ms){
        return ms;
    }
    else{
        return [[self class] instanceMethodSignatureForSelector:@selector(noSelector)];
    }
}

- (void)noSelector{
    NSLog(@"完啦完啦没有方法");
    
}
- (void)user_forwardInvocation:(NSInvocation *)anInvocation{
    
    @try {
        [self user_forwardInvocation:anInvocation];
        
    } @catch (NSException *exception) {
        //捕获异常,根据exception打印出堆栈信息,同时也避免了程序崩溃
        NSLog(@"我要上报");
        NSLog(@"%@%@%@",exception.name,exception.reason,exception.userInfo);
        [JayStackLogManager outputStackLog];
        //上报
    } @finally {
        
    }
    
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值