iOS消息转发机制

“消息派发系统”(message-dispatch system)

若想令类能够理解某条消息,我们必须实现出对应的方法才行。但是,在编译器向类发送其无法解读的消息时并不会报错,因为在运行期可以继续向类中添加方法,所以编译器在编译时还无法确定类中到底会不会有某个方法的实现。当对象接收到无法解读的消息时,就会启动“消息转发”机制,我们可以经由此过程告诉对象应该如何处理未知消息。

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

动态方法解析:

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

图1

该方法的参数就是那个未知的选择子,其返回值为布尔类型,表示这个类是否能新增一个实例方法用以处理此选择子。在继续往下执行转发机制之前,本类有一个机会处理此选择子方法。假如是一个类方法,那么将会调用另外一个方法,如图2:

图2

备援接收者:

当前接收者还有第二次机会处理未知的选择子,在这一步中,运行期系统会询问是否能将该消息转发给其他的接收者处理。对应的方法如图3:

图3

参数为未知的选择子,如当前接收者能找到备援对象,则将其返回,找不到就返回nil。通过此方案,我们可以用“组合”来模拟出“多重继承”的某些特性。在一个对象内部,可能还有一系列其他对象,该对象可以经由此方法将能够处理某选择子的相关内部对象返回,这样的话,在外界看来好像是该对象亲自处理了这些消息。

完整的消息转发:

如果转发已经到了这一步,那么唯一能做的就是启动完整的消息转发机制了。首先创建NSIvocation对象,把尚未处理的那条消息有关的细节全部封到其中。此对象包含选择子、目标、参数。在出发NSIvocation对象时,”消息派发系统“将亲自出马,把消息指派给目标对象。会调用图4的方法来转发消息:

图4

这个方法的实现可以写的很简单,只需要改变调用目标,使消息在新目标上得以调用即可。然而这样实现出来的方法与”备援接收者“反感所实现的方法等效,所以很少有人采用这么简单的实现方式。比较有用的实现方式为:在触发消息前,先以某种方式改变消息内容,比如追加另外一个参数,或者是改换选择子等等。实现此方法时若发现不应该由本类处理,则需要调用超类的同名方法。这样的话,集成体系中的每个类都有机会处理此调用请求,直至NSObject。如果最后调用了NSObject类的方法,那么该方法还会继而调用”doesNotRecognizeSelector:“以抛出异常,此异常表明选择子最终未能得到处理。

消息转发流程:

下面这张图描述了消息转发机制处理消息的各个步骤:根据重复理解一下过程就很明朗了(*^__^*) ……

图5

接收者在每一步中均有机会处理消息。步骤越往后,处理消息的代价就会越大。最好能在第一步就完成,这样的话,运行期系统就可以将此方法缓存起来。如果这个类的实例后面还收到同名的选择子,那么根本就无须启动消息转发流程。若想在第三部把消息转发给备援接收者,还不如把转发操作提前到第二部。以为第三部只是修改了调用目标,这项改动放在第二部执行的话会更加简单,不然还得创建并处理完整的NSIvocation。

以完整的例子演示动态方法解析:

为了说明消息转发机制的意义,下面示范如何以动态方法解析来实现@dynamic属性。假设要编写一个类似于”字典的对象“,它里面可以容纳其他对象,只不过开发者要直接通过属性来存取其中的数据。这个类的设计思路是:由开发者来添加数据定义,并将其声明为@dynamic,而类则会自动处理相关属性值得存放与获取操作。

本例的关在在resolveInstanceMethod:方法的实现:

demo地址:https://github.com/MaxIsComing/MAXAutoDictionary
参考:http://www.jianshu.com/p/60f19a844f18

iOS消息转发机制的更多相关文章

  1. iOS 消息转发机制

    这篇博客的前置知识点是 OC 的消息传递机制,如果你对此还不了解,请先学习之,再来看这篇.这篇博客我尝试用口语的方式像讲述 PPT 一样给大家讲述这个知识点. 我们来思考一个问题,如果对象在收到无法解 ...

  2. iOS的消息转发机制详解

    iOS开发过程中,有一类的错误会经常遇到,就是找不到所调用的方法,当然这类问题比较好解决,给当前对象或其父类对象添加该方法即可,使得编译器在编译时能正确找到该方法:或者,还有另外的方法,由于Objec ...

  3. iOS Runtime的消息转发机制

    前面我们已经讲解Runtime的基本概念和基本使用,如果大家对Runtime机制不是很了解,可以先看一下以前的博客,会对理解这篇博客有所帮助!!! Runtime基本概念:https://www.cn ...

  4. iOS runtime探究(二): 从runtime開始深入理解OC消息转发机制

    你要知道的runtime都在这里 转载请注明出处 http://blog.csdn.net/u014205968/article/details/67639289 本文主要解说runtime相关知识, ...

  5. iOS消息转发

    消息转发是一种功能强大的技术,可以大大增加Objective-C的表现力.什么是消息转发?简而言之,它允许未知的消息被困住并作出反应.换句话说,无论何时发送未知消息,它​​都会以一个很好的包发送到您的 ...

  6. Effective Objective-C 2.0 — 第12条:理解消息转发机制

    11 条讲解了对象的消息传递机制 12条讲解对象在收到无法解读的消息之后会发生什么,就会启动“消息转发”(message forwarding)机制, 若对象无法响应某个选择子,则进入消息转发流程. ...

  7. 理解Objective-C Runtime(三)消息转发机制

    消息转发机制概述 上一篇博客消息传递机制中讲解了Objective-C中对象的「消息传递机制」.本文需要讲解另外一个重要问题:当对象受到无法处理的消息之后会发生什么情况? 显然,若想令类能理解某条消息 ...

  8. runtime消息转发机制

    Objective-C 扩展了 C 语言,并加入了面向对象特性和 Smalltalk 式的消息传递机制.而这个扩展的核心是一个用 C 和 编译语言 写的 Runtime 库.它是 Objective- ...

  9. iOS 消息转发以及 NSProxy 实战

    最后更新: 2018-01-17 一.消息派发机制-NSObject 在 iOS 开发中, 调用对象的方法就是给对象发送一个消息.了解消息的派发机制对于iOS开发来说是一个很实用且强大的工具, 下面我 ...

随机推荐

  1. matlab第一个小应用

    今天安装了matlab,以前还是上线性代数的时候,老师让用过,以及水了一次数模的时候玩了一下.以前太年轻,总觉得这个用处不大虽然别人一直强调这个神器... 到了自己要用的时候才会意识到.大家可能也都听 ...

  2. wareshark网络协议分析之ARP

    一.ARP协议简介 简单的说ARP协议就是实现ip地址到物理地址的映射.当一台主机把以太网数据帧发送到位于同一局域网上的另一台主机时,是根据48bit的以太网地址(物理地址)来确定网络接口的. ARP ...

  3. DataX的安装

    DataX的安装 1. 可下载tar包 https://github.com/alibaba/DataX/blob/master/userGuid.md 2. 下载源码自己编译 git clone h ...

  4. ifconfig源代码分析

    一.ifconfig显示 [root@10g-host4 new]# ifconfig eth0 Link encap:Ethernet HWaddr 00:26:B9:4A:FC:EA inet a ...

  5. 关于series的统计

    1.统计se中各个元素出现的次数: se.value_counts() 这个命令就非常重要!(df没有这个命令) 另外series转dict是to_dict(),注意与数组转list的tolist() ...

  6. Db2数据库在Linux下的安装和配置

    一.DB2数据库的安装和配置: 1.安装完成后,需要增加三个操作系统的组和三个操作系统用户,如下: groupadd -g 999 db2iadm1  #(管理实例的组) groupadd -g 99 ...

  7. http://www.cnblogs.com/jscode/archive/2012/09/03/2669299.html

    http://www.cnblogs.com/jscode/archive/2012/09/03/2669299.html

  8. php特级课---3、常用的网站加速技术有哪些

    php特级课---3.常用的网站加速技术有哪些 一.总结 一句话总结:网站加速技术是一组技术的组合,来提升网站的速度 1.Squid代理缓存技术 2.页面静态化缓存 3.Memcache 4.Sphi ...

  9. vue项目打包注意的地方

    打包有两种方式: 第一种方式:1.更改config文件夹下prod.env.js下的地址: 2.将config文件夹下index.js中build下改为 assetsPublicPath: '', 第 ...

  10. 16 Python 递归函数

    递归 1.什么是递归 recursion 递归 递归的定义——在一个函数里再调用这个函数本身 在一个函数里再调用这个函数本身,这种魔性的使用函数的方式就叫做递归. 递归的最大深度——997 一个函数在 ...