回顾日记3-消息转发机制

当一个对象接收到无法解读的消息时,就会启动消息转发(message forwording)机制。coder可经由此过程告诉对象应该如何处理位置消息。例如给某一个对象实例发送了一个该对象不存在的方法,最后就会crash掉。

-[NSCFDictionary indexOfObject:]: unrecognized selector sent to instance 0x233300555

进行一次发送消息会在相关的类对象中搜索方法列表,如果找不到则会沿着继承树向上一直搜索知道继承树根部(通常为NSObject),如果还是找不到并且消息转发都失败了就回执行doesNotRecognizeSelector:方法报unrecognized selector错。那么消息转发到底是什么呢?接下来将会逐一介绍最后的三次机会。

消息转发分为两大阶段。

第一阶段先询问接受对象所属的类是否能够动态添加方法,以处理这个unknown selector,这叫做动态方法解析(dynamic method resolution).

第二阶段设计完整的消息转发机制(full forwording mechanism)。

如果在运行期,系统已经把第一阶段执行完了,那么接受者自己就无法再以动态添加方法的方式来响应包含该unknown selector的消息了。此时,运行期系统会请求接受者以

其他手段来处理与消息相关的方法调用。这里又分为两小步:

2.1 首先,接受者查看是否有其他对象能处理这条消息,若有,则运行时系统会将消息转给那个对象,一切如常。

2.2 若没有可替代的接受者(replacement receiver),则启动完整的消息转发机制,运行时系统会把与消息有关的全部细节都封装到NSInvocation对象中,再给接受者最后一次机会,令其设法解决当前还未处理的消息。

所属类动态方法解析

//实例方法使用这个 +(BOOL)resolveInstanceMethod:(SEL)sel;

//类方法使用这个 +(BOOL)resolveClassMethod:(SEL)sel;


1


2

如果上述返回NO的话,就是不做动态方法解析,就会进行到下一步

备援接收者

当对象所属类不能动态添加方法后,runtime就会询问当前的接受者是否有其他对象可以处理这个未知的selector,相关方法声明如下:

- (id)forwardingTargetForSelector:(SEL)aSelector;

该方法的参数就是那个未知的selector,这是一个实例方法,因为是询问该实例对象是否有其他实例对象可以接收这个未知的selector,如果没有就返回nil,可以自行实验。

消息重定向

当没有备援接收者时,就只剩下最后一次机会,那就是消息重定向。这个时候runtime会将未知消息的所有细节都封装为NSInvocation对象,然后调用下述方法:

- (void)forwardInvocation: (NSInvocation*)invocation;

调用这个方法如果不能处理就会调用父类的相关方法,一直到NSObject的这个方法,如果NSObject都无法处理就会调用doesNotRecognizeSelector:方法抛出异常。

下图是整个消息转发机制


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

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,758评论 0 9
  • 我们常常会听说 Objective-C 是一门动态语言,那么这个「动态」表现在哪呢?我想最主要的表现就是 Obje...
    Ethan_Struggle阅读 2,230评论 0 7
  • 参考链接: http://www.cnblogs.com/ioshe/p/5489086.html 简介 Runt...
    乐乐的简书阅读 2,153评论 0 9
  • 目录 Objective-C Runtime到底是什么 Objective-C的元素认知 Runtime详解 应用...
    Ryan___阅读 1,950评论 1 3
  • 对象在收到无法解读的消息会发生什么? 若想令类理解某条消息,必须有对应的实现方法.但是,在编译期间动态像对象添加方...
    有一种再见叫青春阅读 594评论 0 2