前言:
objc_msgSend流程图.png
OC的消息机制 objc_msgSend(消息接受者,消息名称)
- OC中方法的调用,其实都是转换为objc_msgSend函数的调用。
- 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