专栏首页王大锤理解消息转发机制

理解消息转发机制

  消息转发分为两大阶段。第一阶段先征询接收者,所属的类,看其是否能动态添加方法,以处理当前这个“未知的选择子”(unknown selector),这叫做“动态方法解析”(dynamic method resolution)。第二阶段涉及“完整的消息转发机制”。如果运行期系统已经把第一阶段执行完了,那么接收者自己就无法再以动态新增方法的手段来响应包含该选择子的消息了。此时,运行期系统会请求接收者以其他手段来处理与消息相关的方法调用。这又细分为两小步。首先,请接收者看看有没有其他对象来处理这条消息。若有,则运行期系统会把消息转发给那个对象,于是消息转发过程结束,一切如常。若没有“备援的接收者”,则启动完整的消息转发机制,运行期系统会把与消息有关的全部细节都封装在NSInvocation对象中,再给接收者最后一次机会,令其设法解决当前还未处理的这条消息。

  注意:选择子就是方法,就是@selector(methodName)这个玩意,也叫方法选择器。

  一,动态方法解析

  对象在收到无法解读的消息后,首先将调用其所属类的下列类方法:

+  (BOOL)resolveInstanceMethod:(SEL)selector

  该方法的参数就是那个未知的选择子,其返回值为Boolean类型,表示这个类是否能新增一个实例方法用以处理此选择子。

  如果是类方法,则会调用:

+ (BOOL)resolveClassMethod:(SEL)selector

使用这种方法的前提是:相关方法的实现代码已经写好,只等运行的时候动态插在类里面就可以了。

  二,完整的消息转发

  如果运行期系统已经执行完了动态方法解析,消息还没有被处理,那么消息接受者自己就无法再以动态新增方法的形式来响应包含该未知选择子的消息了,此时就进入了第二阶段——完整的消息转发。运行期系统会请求消息接受者以其他手段来处理与消息相关的方法调用。

  1 备援接收者

  当前接收者还有第二次机会能处理未知的选择子,在这一步中运行期系统会问它:能不能把这条消息转给其他接收者来处理。就会调用如下方法:

- (id)forwardingTargetForSelector:(SEL)selector

这里的返回值,就是备援接收者,它会继续处理这个消息。

在一个对象内部,可能还有一系列其他对象,该对象可经由此方法将能够处理某选择子的相关内部对象返回,这样的话,在外界看来,好像是该对象亲自处理了这些消息似的。

  2 完整的消息转发

  如果消息还没有被处理,转发算法就会来到这一步。首先创建NSInvocation对象,把尚未处理的那条消息有关的全部细节都封装其中。“消息派发系统”将把消息指派给目标对象。这里的目标对象可以自定义。此步骤会调用下列方法:

 (void)forwardInvocation:(NSInvocation *)invocation

实现此方法时,如果发现调用操作不应该由本类处理,则需要沿着继承体系,调用父类的同名方法,这样一来,继承体系中的每个类都有机会处理这个调用请求,直至rootClass,也就是NSObject类。如果最后调用了NSObject的类方法,那么该方法还会继而调用”doesNotRecognizeSelector:“以抛出异常,此异常表明选择子最终也未能得到处理。消息转发到此结束。

关于does NotRecognizeSelector:你可能感到陌生,但是对于类似于unrecognized selector send to instance xxx这样的错误,你可能并不陌生。这种错误通常是因为调用了某个对象或者某个类里不存在的方法,从而触发了消息转发机制,最终把这个未识别的消息发送给了NSObject的默认实现。

三,消息转发全流程:

摘录自《Effetive Objective-C 2.0 编写高质量iOS与OS X代码的52个有效方法》第12条:理解消息转发机制

DEMO1:https://github.com/caigee/iosdev_sample下的ClassForward

DEMO2:https://github.com/huanglonghui/MessageForwardingTest

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 理解消息转发机制

    王大锤
  • github for Mac 教程

    王大锤
  • 巧用 Class Extension 隐藏属性

    一般来说,Extension用来给Class增加私有属性和方法,写在 Class 的.m文件。但是Extension不是必须要写在.m文件,你可以写在任何地方,...

    王大锤
  • 理解消息转发机制

    王大锤
  • iOS RunTime之四:消息转发

    在消息转发机制执行前,Runtime 系统会再给我们一次偷梁换柱的机会,即通过重载 - (id)forwardingTargetForSelector:(SEL...

    s_在路上
  • 京城第一ACG&VR大趴|北京数字娱乐节·跨次元盛夏祭·群星璀璨

    VRPinea
  • 分布式事务—两阶段提交协议

    两阶段提交协议(Two-phase Commit,2PC)经常被用来实现分布式事务。一般分为协调器C和若干事务执行者Si两种角色,这里的事务执行者就是具体的数据...

    江湖前辈黄药师
  • python开发_python关键字

    The following identifiers are used as reserved words, or keywords of the languag...

    Hongten
  • 《Spring设计思想》AOP设计思想与原理

    Spring 提供了AOP(Aspect Oriented Programming) 的支持, 那么,什么是AOP呢?本文将通过一个另外一个角度来诠释AOP的概...

    java思维导图
  • 《Spring设计思想》AOP设计基本原理

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://louluan.blog.c...

    亦山

扫码关注云+社区

领取腾讯云代金券