iOS objc_msgSend消息发送机制

前言:

objc_msgSend流程图.png

OC的消息机制 objc_msgSend(消息接受者,消息名称)

  1. OC中方法的调用,其实都是转换为objc_msgSend函数的调用。
  2. objc_msgSend的执行流程可以分为3个阶段
  • 消息发送
    流程:[receiver method]调用的时候先判断receiver是否为nil,为nil直接退出调用流程,否则从方法receiver的方法cache列表中找,找到方法进行调用结束,否则会从receiver的class_rw_t 方法列表中找,找到调用结束,否则进行父类的cache列表中找,进而父类的class_rw_t中找,循环直至找到方法进行调用,当superClass为nil时,进行动态解析。
    objc_msgSend执行流程
  • 动态方法解析
    流程: 当触发动态解析的时候,先判断是否已经解析过,解析过则执行下一步消息转发,否则会调用resolveInstanceMethod:resolveClassMethod:方法的动态解析的方法,然后标记为已经动态解析,最后会进入消息发送的流程(receiver的cache列表中开始寻找),进行寻找方法调用。
    动态解析过程
  • 消息转发(apple并没有将这步骤开源)
    流程: 当前消息发送,跟动态解析都没有找到方法的实现的时候,系统会认为该类没有实现该方法的能力,会进入消息转发的过程,即会调用 (id)forwardingTargetForSelector:(SEL)aSelector
    方法来进一步查看是否有处理该类的方法。
    如果返回不为空,则直接给该对象发送消息,进行函数调用。
    如果为空,则进入下一个流程
    -(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
    返回一个方法签名,编码符: v16@0:8 返回值为空 viod 默认 self 跟_cmd两个参数 16个字节
    不为空,则调用-(void)forwardInvocation:(NSInvocation *)anInvocation这是最后一步调用机制,如果内部没有实现,则会抛出异常。
//消息转发
- (id)forwardingTargetForSelector:(SEL)aSelector {
    if (aSelector == @selector(test)) {
        //消息转发 不为空直接调用
//        return [JWCat new];
        //为空
        return nil;
    }
    return [super forwardingTargetForSelector:aSelector];
}
//消息转发为空
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    if (aSelector == @selector(test)) {
        //v16@0:8  返回值为空 viod  默认 self 跟_cmd两个参数 16个字节
        return [NSMethodSignature signatureWithObjCTypes:"v16@0:8"];
    }
    return [super methodSignatureForSelector:aSelector];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
    //包装NSMethodSignature 签名的一个地方
    [anInvocation invokeWithTarget:[JWCat new]];
}

以上3个阶段都没有找到,会报错unrecognized selector sent to instance

你可能感兴趣的:(iOS objc_msgSend消息发送机制)