- 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、 从receiverClass
的 cache
中查找方法,找到了调用方法,结束查找,没找到进行 3
3、从receiverClass
的 class_rw_t
的方法列表中查找方法,找到了调用方法,结束查找,并将方法缓存到receiverClass
的 cache
中,没找到进行 4
4、 从 superClass
的 cache
中查找方法,找到了调用方法,结束查找,并将方法缓存到receiverClass
的 cache
中,没找到进行 5
5、从superClass
的 class_rw_t
的方法列表中查找方法,找到了调用方法,结束查找,并将方法缓存到receiverClass
的 cache
中,没找到进行 6
6、 上层是否还有 superClass
,有进行 4,没有进入到动态方法解析
动态方法解析
1、 是否进行过动态解析,如果是,则进行消息转发,如果否,进行 2
2、调用+resolveInstanceMethod:
或者-resolveClassMethod:
方法来动态解析方法.
3、标记为已动态解析
4、消息发送
-
为什么动态方法解析完最后又走消息发送? 这里是这样的,添加完了还没调用,所以又走一遍消息发送,会重新开始从方法缓存列表中查找方法,如果还是没找到,说明没有动态添加方法,但这时已经标记为动态解析过了,不会再动态解析了.然后就会进行消息转发了.
-
+resolveInstanceMethod方法的实现
注意:
如果是添加实例方法,在调用 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
方法.
这里需要注意下面几点:
-
forwardingTargetForSelector:
、methodSignatureForSelector:
、forwardInvocation:
这三个方法都是既有实例方法又有类方法,当调用者是类的时候走的是类方法,当调用者是对象的时候走的是对象方法. - 如果实现了
forwardingTargetForSelector:
方法,那么该方法返回的对象必须是实现了SEL
方法的对象,不然会报找不到方法的错误. -
methodSignatureForSelector
与forwardInvocation
需要一起实现,只实现其中一个没有作用. -
methodSignatureForSelector
返回的方法签不需要与传进来的 SEL一至 -
forwardInvocation
的实现可以使用传进来的anInvocation
,也可以不使用,在这个方法的实现了你可以做任何事情,或者什么事情都不做也可以,只要你实现了这个方法就代表消息得到了转发.
forwardingTargetForSelector
被认为是快速消息转发,而methodSignatureForSelector
和forwardInvocation
被认为是正常消息转发,不知道苹果为什么会设计这两种消息转发模式
NSProxy 专门用来做消息转发的