Runtime之msgSend探究

2021-06-28  本文已影响0人  飞翔的船

OC中的方法调用,其实都是转换为objc_megSend函数调用。

objc_megSend的执行流程可以分为3大阶段

消息发送流程

消息发送.png

动态方法解析

流程

动态方法解析.png

动态添加方法

当消息发送进入动态方法解析阶段,调用+resolveInstanceMethod:+resolveClassMethod:方法时,可以在此时动态的添加方法。

有两种动态添加方法的方式。

  1. 动态其他OC方法

    @interface GLPerson : NSObject
    - (void) abc;
    @end
      
    #import <objc/runtime.h>
    @implementation GLPerson
    
    - (void) other {
        NSLog(@"%@",NSStringFromSelector(_cmd));
        NSLog(@"%s",__func__);
    }
    
    + (BOOL)resolveInstanceMethod:(SEL)sel {
        if (sel == @selector(abc)) {
             //将other方法的实现添加。Method可以理解为等价于struct method_t *
            Method method = class_getInstanceMethod(self, @selector(other));
            class_addMethod(self,
                            sel,
                            method_getImplementation(method),
                            method_getTypeEncoding(method));
            return  YES;
        }
        return [super resolveInstanceMethod:sel];
    }
    @end
      
    //// ===== main
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            GLPerson *person = [[GLPerson alloc] init];
            [person abc];
          
        }
        return 0;
    }
    //程序输出:
    //abc
    /-[GLPerson other]
    
  2. 动态添加C语言函数

    @interface GLPerson : NSObject
    - (void) abc;
    @end
      
    #import <objc/runtime.h>
    @implementation GLPerson
    
    - (void) other {
        NSLog(@"%@",NSStringFromSelector(_cmd));
        NSLog(@"%s",__func__);
    }
    
    + (BOOL)resolveInstanceMethod:(SEL)sel {
        if (sel == @selector(abc)) {
             class_addMethod(self,
                            sel,
                            /* C语言的函数名就是函数地址 */
                            (IMP)other,
                            "v16@0:8");
            return  YES;
        }
        return [super resolveInstanceMethod:sel];
    }
    @end
      
    //// ===== main
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            GLPerson *person = [[GLPerson alloc] init];
            [person abc];
          
        }
        return 0;
    }
    //程序输出:
    //abc
    //self=<GLPerson: 0x10301a950>
    

消息转发流程

消息转发,顾名思义就是将消息转发给别的对象。

消息转发.png

当方法调用来到消息转发阶段:

上一篇 下一篇

猜你喜欢

热点阅读