美文网首页
08.Objective-C 消息机制

08.Objective-C 消息机制

作者: ProfessorFan | 来源:发表于2022-05-17 11:42 被阅读0次

    问题 消息机制的三个阶段

    1.消息机制发送消息阶段-消息发送
    2.消息机制动态方法解析阶段 -动态解析
    3.消息机制消息转发阶段- 消息转发
    4.线上项目中解决找不到方法奔溃

    解决方案

    1.消息机制发送消息阶段-消息发送
    常用对象方法:
    实例对象通过isa 指针 和 某一个值 发生一个位运算 得到该实例的类对象 ,类对象的两个方法列表中(cache_t,method_list_t )寻找对应的方法 如果没有找到,之后通过类对象的superClass 指针找到 父类的类对象中(cache_t,method_list_t)寻找,直到找到root类的类对象为止,这就是消息发送
    常用类方法:
    类对象通过isa 指针 和 某一个值 发生一个位运算 得到元类对象 ,元类的两个方法列表中(cache_t,method_list_t )寻找对应的方法 如果没有找到,之后通过元类对象的superClass 指针找到 父类的类对象中(cache_t,method_list_t)寻找,直到找到root元类的类对象为止,这就是消息发送

    2.消息机制动态方法解析阶段 -动态解析
    动态解析触发机制:
    消息发送没有 找到对应的方法,就会出发消息的动态解析
    a.动态解析C语言函数

    
    void c_other(id self, SEL _cmd)
    {
        NSLog(@"c_other - %@ - %@", self, NSStringFromSelector(_cmd));
    }
    
    + (BOOL)resolveClassMethod:(SEL)sel
    {
        if (sel == @selector(test)) {
            // 第一个参数是object_getClass(self)
            class_addMethod(object_getClass(self), sel, (IMP)c_other, "v16@0:8");
            return YES;
        }
        return [super resolveClassMethod:sel];
    }
    + (BOOL)resolveInstanceMethod:(SEL)sel
    {
        if (sel == @selector(test)) {
            // 动态添加test方法的实现
            class_addMethod(self, sel, (IMP)c_other, "v16@0:8");
    
            // 返回YES代表有动态添加方法
            return YES;
        }
        return [super resolveInstanceMethod:sel];
    }
    

    b.动态解析OC函数

    - (void)other
    {
        NSLog(@"%s", __func__);
    }
    
    + (BOOL)resolveInstanceMethod:(SEL)sel
    {
        if (sel == @selector(test)) {
            // 获取其他方法
            Method method = class_getInstanceMethod(self, @selector(other));
    
            // 动态添加test方法的实现
            class_addMethod(self, sel,
                            method_getImplementation(method),
                            method_getTypeEncoding(method));
    
            // 返回YES代表有动态添加方法
            return YES;
        }
        return [super resolveInstanceMethod:sel];
    }
    

    3.消息机制消息转发阶段- 消息转发
    消息转发触发机制:
    动态解析 resolveInstanceMethod方法为 NO
    a.消息转发函数

    - (id)forwardingTargetForSelector:(SEL)aSelector
    {
        if (aSelector == @selector(test)) {
            // objc_msgSend([[MJCat alloc] init], aSelector)
            return [[MJCat alloc] init];
        }
        return [super forwardingTargetForSelector:aSelector];
    }
    

    b.如果消息转发函数也返回nil,现在就是方法签名

     方法签名:返回值类型、参数类型
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
    {
        if (aSelector == @selector(test)) {
            return [NSMethodSignature signatureWithObjCTypes:"v16@0:8"];
        }
        return [super methodSignatureForSelector:aSelector];
    }
    
    // NSInvocation封装了一个方法调用,包括:方法调用者、方法名、方法参数
     //   anInvocation.target 方法调用者
      //  anInvocation.selector 方法名
    //    [anInvocation getArgument:NULL atIndex:0]
    - (void)forwardInvocation:(NSInvocation *)anInvocation
    {
    //    anInvocation.target = [[MJCat alloc] init];
    //    [anInvocation invoke];
    
        [anInvocation invokeWithTarget:[[MJCat alloc] init]];
    }
    

    4.线上项目中解决找不到方法奔溃

    @implementation NSBaseObject (bugSolve)
    
    - (void)run
    {
        NSLog(@"run-123");
    }
    
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
    {
        // 本来能调用的方法
        if ([self respondsToSelector:aSelector]) {
           
            return [super methodSignatureForSelector:aSelector];
        }
        
        // 找不到的方法
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }
    
    // 找不到的方法,都会来到这里
    - (void)forwardInvocation:(NSInvocation *)anInvocation
    {
        NSLog(@"找不到%@方法", NSStringFromSelector(anInvocation.selector));
    }
    
    @end
    

    相关文章

      网友评论

          本文标题:08.Objective-C 消息机制

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