objc_msgSend执行流程

objc_msgSend执行流程

OC中方法调用,其实都是转换成objc_msgSend函数调用
objc_msgSend的执行流程可以分为3个阶段

  1. 消息发送
  2. 动态方法解析
  3. 消息转发
1.消息发送

消息发送
上图就是消息发送阶段的过程,如果查找到最顶级的类,仍然没有找到相应的方法,则会进入下一个阶段

2. 动态方法解析

动态方法解析
我们在这一步中动态添加的方法,是添加到当前类/当前元类 的class_rw_t表中,调用之后,方法会缓存在cache表中 (cache表底层是通过散列表实现的,效率高,这里散列表的大概实现原理是通过key值&MASK得到一个序号(这个序号可能是相同,可能不是放在首位),这样通过序号可以直接找到当前存储的对象,通过key拿到value)

// 动态添加实例方法,添加的方法存在对象的方法列表中
+ resolveInstanceMethod: 
  1. 在程序运行阶段动态添加一个实例方法
struct method_t {
    SEL sel;
    char *types;
    IMP imp;
};

- (void)testABC {
    NSLog(@"%s",__func__);
}

+ (BOOL)resolveInstanceMethod:(SEL)sel {
    
    if (sel == @selector(test)) {
        
        struct method_t *method = (struct method_t *)class_getInstanceMethod(self, @selector(testABC));
        
        class_addMethod(self, sel, method->imp, method->types);
        
        return YES;
    }
    
    return [super resolveInstanceMethod:sel];
}

还可以这么写

- (void)testABC {
    NSLog(@"%s",__func__);
}

+ (BOOL)resolveInstanceMethod:(SEL)sel {
    
    if (sel == @selector(test)) {
        
        Method method = class_getInstanceMethod(self, @selector(testABC));
        
        class_addMethod(self, sel, method_getImplementation(method), method_getTypeEncoding(method));
        
        return YES;
    }
    
    return [super resolveInstanceMethod:sel];
}
  1. 在程序运行阶段动态添加一个类方法
+ (BOOL)resolveClassMethod:(SEL)sel {
    if (sel == @selector(test)) {
        
        Method method = class_getInstanceMethod(self, @selector(other));
        
        // 这里是往元类中添加方法,所以需要通过object_getClass获取元类
        class_addMethod(object_getClass(self), sel, method_getImplementation(method), method_getTypeEncoding(method));
        
        return YES;
    }
    return [super resolveClassMethod:sel];
}
3. 消息转发

消息转发

消息转发

- (id)forwardingTargetForSelector:(SEL)aSelector
{
    if (aSelector == @selector(test)) {
        // 交给student类处理
        return [[MJStudent alloc] init];
    }
    // 如果这里不处理的话,走方法 methodSignatureForSelector:
    return [super forwardingTargetForSelector:aSelector];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    if (aSelector == @selector(test)) {
        // 如果这里处理了,会走方法 forwardInvocation:
        // v16@0:8 是方法签名
        return [NSMethodSignature signatureWithObjCTypes:"v16@0:8"];
    }
    return [super methodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    // 这里可以随意处理
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值