oc 的消息机制

  • OC 中的方法调用,其实都是转换为 objc_msgSend函数的调用的.比如
NSObject *obj = [[NSObject alloc] init];
[obj copy];

[obj copy]; 就会转化为 objc_msgSend(obj,@selector(copy));第一个参数是消息接收者(receiver),第二个参数是消息名称(SEL).

objc_msgSend 执行流程

消息发送

1、判断 receiver 是否为 nil,如果是,则直接退出,如果不是进行 2
2、 从receiverClasscache 中查找方法,找到了调用方法,结束查找,没找到进行 3
3、从receiverClassclass_rw_t 的方法列表中查找方法,找到了调用方法,结束查找,并将方法缓存到receiverClasscache 中,没找到进行 4
4、 从 superClasscache 中查找方法,找到了调用方法,结束查找,并将方法缓存到receiverClasscache 中,没找到进行 5
5、从superClassclass_rw_t的方法列表中查找方法,找到了调用方法,结束查找,并将方法缓存到receiverClasscache 中,没找到进行 6
6、 上层是否还有 superClass,有进行 4,没有进入到动态方法解析

image.png
动态方法解析

1、 是否进行过动态解析,如果是,则进行消息转发,如果否,进行 2
2、调用+resolveInstanceMethod:或者-resolveClassMethod:方法来动态解析方法.
3、标记为已动态解析
4、消息发送

  • 为什么动态方法解析完最后又走消息发送? 这里是这样的,添加完了还没调用,所以又走一遍消息发送,会重新开始从方法缓存列表中查找方法,如果还是没找到,说明没有动态添加方法,但这时已经标记为动态解析过了,不会再动态解析了.然后就会进行消息转发了.


    动态方法解析
  • +resolveInstanceMethod方法的实现


    image.png
image.png

注意:如果是添加实例方法,在调用 class_addMethod方法的时候第一个参数传类对象,如果是添加类方法,在调用class_addMethod方法的时候第一个参数传元类对象.

消息转发

1、调用 (id)forwardingTargetForSelector:(SEL)aSelector方法,如果返回值不为 nil,则调用 objc_msgSend(返回值,SEL).如果返回值为 nil,则进行 2
2、调用 (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector方法,如果返回值为 nil,则调用 doesNotRecognizeSelector:方法,如果不为nil,则进行 3. 获得NSMethodSignature的方式有两种[NSMethodSignature signatureWithObjCTypes:"v16@0:8"];[NSObject methodSignatureForSelector:aSelector] / [[NSObject new] methodSignatureForSelector:aSelector]
3、调用(void)forwardInvocation:(NSInvocation *)anInvocation方法.

image.png

这里需要注意下面几点:

  • forwardingTargetForSelector:methodSignatureForSelector:forwardInvocation:这三个方法都是既有实例方法又有类方法,当调用者是类的时候走的是类方法,当调用者是对象的时候走的是对象方法.
  • 如果实现了forwardingTargetForSelector:方法,那么该方法返回的对象必须是实现了 SEL方法的对象,不然会报找不到方法的错误.
  • methodSignatureForSelectorforwardInvocation需要一起实现,只实现其中一个没有作用.
  • methodSignatureForSelector返回的方法签不需要与传进来的 SEL一至
  • forwardInvocation的实现可以使用传进来的anInvocation,也可以不使用,在这个方法的实现了你可以做任何事情,或者什么事情都不做也可以,只要你实现了这个方法就代表消息得到了转发.

forwardingTargetForSelector 被认为是快速消息转发,而methodSignatureForSelectorforwardInvocation被认为是正常消息转发,不知道苹果为什么会设计这两种消息转发模式

NSProxy 专门用来做消息转发的

你可能感兴趣的:(oc 的消息机制)