美文网首页
runtime 消息机制简析

runtime 消息机制简析

作者: 刺客小生110 | 来源:发表于2018-11-16 15:48 被阅读1次

    runtime 消息机制
    消息机制可以简单分为三个方面:消息发送、动态方法解析、消息转发
    一.消息发送
    oc 中所有的方法调用最终会通过 runtime 转换为objc_msgSend(obj,@selector(sendMassage))这个函数,有两个隐藏的参数:代表对象的类型、函数对应的方法的编号(SEL),然后通过以下顺序寻找调用:

    1.通过obj的isa指针找到其所对应的类
    2.通过SEL寻找方法是否存在(1、cache—>2.类的方法列表—>父类----->NSObject)
    3.找到之后寻找方法实现(IMP)
     寻找 imp 的方法
    i   class_getMethodImplementation(Class cls, SEL name);
    ii   method_getImplementation(Method m)
    4.调用 imp(self, _cmd, ...)
    

    至此 OC 的消息发送就完成,如果在上述过程中没有对应的方法或者实现,那么OC 的消息机制也会提供其他的机会来防止程序崩溃:动态方法解析和消息转发

    二、动态方法解析
    如果在消息的发送过程中没有找到对应的方法OC消息机制会提供一个动态解析方法的机会,让我们来动态添加方法的实现
    resolveInstanceMethod、 resolveClassMethod

    下面是一个🌰:一个看类中掉用了 unImpMethod()方法
    但是并未写方法的实现当我们调用的时候会先走第一部分的流程,然后发现并没有找到对应的 imp,此时我们可以通过resolveInstanceMethod来添加一个 imp

    //增加一个方法
    void esolveInstanceTest(){
        NSLog(@"添加啦啦啦啦啦");
    }
    //动态解析方法
    +(BOOL)resolveInstanceMethod:(SEL)sel{
        if (sel == @selector(unImpMethod)) {
    //动态解析时添加一个方法
            class_addMethod([self class], sel, (IMP) esolveInstanceTest, "v@:");
        }
        return [super resolveInstanceMethod:sel];
    }
    

    态解析过程添加IMP并且返回了 yes 就可以完成调用,当这个方法返回no时或者没有实现时会进入消息转发。

    三、消息转发
    消息转发可以分为两个步骤,
    1.先通过forwardingTargetForSelector返回一个实现了该方法的对象。如果此时的对象任然不能响应就会进入消息转发下一个阶段

    //该方法返回一个添加了方法实现的对象,
    -(id)forwardingTargetForSelector:(SEL)aSelector{
        if (aSelector == @selector(unImpMethod)) {
        //studentTest类中这个方法有实现
            ForwardingTarget *forwardingTarget = [[ForwardingTarget alloc]init];
            return forwardingTarget;
        }
        return [super forwardingTargetForSelector:aSelector];
    }
    

    2.runtime需要生成一个methodSignature变量来组装一个NSInvocation对象进行最后一次的消息转发

    //这个方法返回一个NSMethodSignature*的对象,里面打包了有关于这个未实现方法的信息
    -(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
        NSString*sel = NSStringFromSelector(aSelector);
        if ([sel isEqualToString:@"write"]) {
            return [NSMethodSignature signatureWithObjCTypes:"v@:"];
        }
        return [super methodSignatureForSelector:aSelector];
    }
    
    -(void)forwardInvocation:(NSInvocation *)anInvocation{
        SEL selector = [anInvocation selector];
        StudentTest *test = [[StudentTest alloc]init];
        if ([test respondsToSelector:selector]) {
            [anInvocation invokeWithTarget:test];
        }
    }
    

    相关文章

      网友评论

          本文标题:runtime 消息机制简析

          本文链接:https://www.haomeiwen.com/subject/lllmfqtx.html