消息发送

2019-02-12  本文已影响0人  愤怒的八哥

消息发送
1.首先,通过obj的isa指针找到它的class;
2.在class的method list找对应方法;
3.如果class中没到对应的方法,继续往它的superclass中找 ;
4.一旦找到对应的方法,就去执行它的实现IMP;

当然了,由于效率的问题,每个消息都遍历一次objc_method_list并不合理。所以需要把经常被调用的函数缓存下来,去提高函数查询的效率。这也就是objc_class中另一个重要成员objc_cache做的事情 - 再找到test之后,把test的method_name作为key,method_imp作为value给存起来。当再次收到test消息的时候,可以直接在cache里找到,避免去遍历objc_method_list。从前面的源代码可以看到objc_cache是存在objc_class结构体中的。

消息转发

1.调用resolveInstanceMethod:方法 (或 resolveClassMethod:)。允许用户在此时为该 Class 动态添加实现。如果有实现了,则调用并返回YES,那么重新开始objc_msgSend流程。这一次对象会响应这个选择器,一般是因为它已经调用过class_addMethod。如果仍没实现,继续下面的动作。
2.调用forwardingTargetForSelector:方法,尝试找到一个能响应该消息的对象。如果获取到,则直接把消息转发给它,返回非 nil 对象。否则返回 nil ,继续下面的动作。注意,这里不要返回 self ,否则会形成死循环。
3.调用methodSignatureForSelector:方法,尝试获得一个方法签名。如果获取不到,则直接调用doesNotRecognizeSelector抛出异常。如果能获取,则返回非nil:创建一个 NSlnvocation 并传给forwardInvocation:。
4.调用forwardInvocation:方法,将第3步获取到的方法签名包装成 Invocation 传入,如何处理就在这里面了,并返回非ni。
5.调用doesNotRecognizeSelector: ,默认的实现是抛出异常。如果第3步没能获得一个方法签名,执行该步骤。

runtime方法
objc_msgSend消息发送;
_objc_msgForward是一个函数指针(和 IMP 的类型一样),是用于消息转发的:当向一个对象发送一条消息,但它并没有实现的时候,_objc_msgForward会尝试做消息转发。
参考:
http://www.cocoachina.com/ios/20180315/22625.html

上一篇下一篇

猜你喜欢

热点阅读