美文网首页iOS 开发继续加油
Runtime消息传递机制

Runtime消息传递机制

作者: 昵称是乱起的 | 来源:发表于2019-01-22 00:29 被阅读73次
    先看下整个Class的底层结构
    image.png

    objc_msgSend的源码是汇编实现的

    objc_msgSend的执行流程01-消息发送
    image.png

    如果是从class_rw_t中查找方法,已经排序的采用二分查找,没有排序的遍历查找
    receiver通过isa指针找到receiverClass
    receiverClass通过superclass指针找到superClass

    objc_msgSend的执行流程02-动态方法解析
    image.png

    动态解析过后,会重新走“消息发送”的流程,“从receiverClass的cache中查找方法”这一步开始执行
    开发者可以实现以下方法,来动态添加方法实现
    +resolveInstanceMethod:
    +resolveClassMethod:

    #InstanceMethod第1种写法
    - (void)other
    {
        NSLog(@"%s",__func__);
    }
    + (BOOL)resolveInstanceMethod:(SEL)sel
    {
        if (sel == sel_registerName("test")) {
            Method method = class_getInstanceMethod(self, sel_registerName("test"));
            class_addMethod(self, sel, method_getImplementation(method), method_getTypeEncoding(method));
            return YES;
        }
        return [super resolveInstanceMethod:sel];
    }
    #InstanceMethod第2种写法
    void c_other(id self, SEL _cmd)
    {
        NSLog(@"c_other - %@ - %@", self, NSStringFromSelector(_cmd));
    }
    + (BOOL)resolveInstanceMethod:(SEL)sel
    {
        if (sel == @selector(test)) {
            class_addMethod(self, sel, (IMP)c_other, "v16@0:8");
            return YES;
        }
        return [super resolveInstanceMethod:sel];
    }
    #InstanceMethod第3种写法
    struct method_t {
        SEL sel;
        char *types;
        IMP imp;
    };
    - (void)other
    {
        NSLog(@"%s",__func__);
    }
    + (BOOL)resolveInstanceMethod:(SEL)sel
    {
        if (sel == @selector(test)) {
            struct method_t *method = (struct method_t *)class_getInstanceMethod(self, @selector(other));
            class_addMethod(self, sel, method->imp, method->types);
            return YES;
        }
        return [super resolveInstanceMethod:sel];
    }
    #ClassMethod写法
    void c_other(id self, SEL _cmd)
    {
        NSLog(@"c_other - %@ - %@", self, NSStringFromSelector(_cmd));
    }
    + (BOOL)resolveClassMethod:(SEL)sel
    {
        if (sel == @selector(test)) {
            class_addMethod(object_getClass(self), sel, (IMP)c_other, "v16@0:8");
            return YES;
        }
        return [super resolveClassMethod:sel];
    }
    
    
    objc_msgSend的执行流程03-消息转发
    image.png
    + (id)forwardingTargetForSelector:(SEL)aSelector
    {
        if (aSelector == @selector(test)) return [[Person alloc] init];
        return [super forwardingTargetForSelector:aSelector];
    }
    //上面return NO才会来到这里
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
    {
        if (aSelector == @selector(test:)) {
            return [NSMethodSignature signatureWithObjCTypes:"i@:i"];
        }
        return [super methodSignatureForSelector:aSelector];
    }
    - (void)forwardInvocation:(NSInvocation *)anInvocation
    {
        [anInvocation invokeWithTarget:[[Person alloc] init]];
    }
    

    @dynamic value;// 提醒编译器不要自动生成setter和getter的实现、不要自动生成成员变量

    super底层
     [self class];
     objc_msgSend(self, sel_registerName("class"))
     [super superclass];
     objc_msgSendSuper({self,class_getSuperclass(objc_getClass("Person"))}, sel_registerName("class")))
    

    相关文章

      网友评论

        本文标题:Runtime消息传递机制

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