对iOS runtime的一点理解(2)

参考这篇文章和我的理解,objc_msgSend方法中,查找一个消息对应的实现的过程大致应该是这样的:

  1. 检测这个selector是不是要忽略的;
  2. 检测这个target是不是nil对象;
    (这两步中,如果消息应该被忽略,那么对应的方法是不会被执行的)
  3. 在receiver对应的类结构中查找selector和它对应的过程,先在cache里找,如果没有命中,就依次在类的方法分发表中查找;
  4. 如果在方法分发表中找不到,就开始查看动态方法;
  5. 如果还找不到就开始执行消息转发逻辑。
动态方法

参考苹果官方文档,如果运行时系统未能在方法分发表中找到消息对应的具体实现,那么将会调用

+(BOOL)resolveInstanceMethod:(SEL)aSEL

方法,程序员可以通过重写这个方法,为receiver类动态的增加selector对应的方法。

消息转发机制

如果经过了动态方法这一步骤,还不能找到消息对应的具体实现,那么运行时系统就会用到消息转发机制。
在进入消息转发机制时,对程序员来说,还有两次转发消息的机会。

一. 备用接收者

如果以上几步都无法处理某个消息,则运行时系统会调用这个方法:

- (id)forwardingTargetForSelector:(SEL)aSelector

从方法名中就可以看出,这个方法返回的对象将作为消息的备用接收者。也就是说,重写这个方法可以控制消息转发到哪个对象上去。

二. 完整消息转发

如果上一步还是没能处理这个消息,那么完整消息转发就成了整个发消息过程的最后一步。运行时系统会调用这个方法:

- (void)forwardInvocation:(NSInvocation *)anInvocation

这个方法应该要完成这两件事情:

  1. 决定这个消息被发送到哪里;
  2. 将这个消息发送到那里。

在重写的这个方法中,程序员还有机会对消息的内容(比如参数等)进行修改。

需要注意的是,在重写这个方法,企图进行消息转发的同时,也需要重写:

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector

参考这个方法的文档methodSignatureForSelector:将先于forwardInvocation:方法调用。消息转发机制需要使用从methodSignatureForSelector:中获取的信息来创建即将被转发的NSInvocation对象。


我自己的一些理解

感觉很多人会把动态方法当作消息转发机制的一部分,但是我觉得这样的理解不是很准确。首先,苹果官方文档上有这么一句话:

Forwarding methods (as described in Message Forwarding) and dynamic method resolution are, largely, orthogonal.

另外,动态方法会被respondsToSelector:methodForSelector:考虑进去,但是消息转发机制并不会。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,776评论 0 9
  • 参考链接: http://www.cnblogs.com/ioshe/p/5489086.html 简介 Runt...
    乐乐的简书阅读 2,158评论 0 9
  • 目录 Objective-C Runtime到底是什么 Objective-C的元素认知 Runtime详解 应用...
    Ryan___阅读 1,962评论 1 3
  • 我们常常会听说 Objective-C 是一门动态语言,那么这个「动态」表现在哪呢?我想最主要的表现就是 Obje...
    Ethan_Struggle阅读 2,232评论 0 7
  • Runtime是什么 Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我...
    SuAdrenine阅读 900评论 0 3