专栏首页正则ios OC 消息转发机制
原创

ios OC 消息转发机制

一 概述

     在编译期向类发送了其无法解读的的消息并不会报错,因为在运行期可以继续让类中添加方法,所有编译器在编译时还无法确知类中到底会不会有某个方法实现,当对象接收到无法解读的消息后,就会启动 消息转发 机制,程序员可经由此过程告诉对象应该如何处理未知消息。

在程序运行中,有时会以下异常信息

[Class function_name ] unrecognized selector sent to instanc

上段信息就是发送一个未识别的消息给实例,类定义但对象未实现function_name 方法

二 消息转发的两大阶段

    第一阶段先征询接受者所属的类,看其是否能动态添加方法,以处理当前“未知的选择子”,叫做“动态方法解析”。

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

2.1动态方法解析

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

+(BOOL)resolveInstanceMethod:(SEL)selector

该方法的参数就是未知的选择子,返回类型为Boolean,表示类是否能新增一个实例方法用以处理此选择子。在继续往下执行转换机制之前,本类可用新增处理此选择子的方法,假如尚未实现的方法不是实例方法而是类方法,那么运行期系统就会调用另外一个方法,该方法与“resolveInstanceMethod:”类似,叫做”resolveClassMethod:” 。

    使用这种办法的前提是:相关方法的代码实现已经写好,只等着运行的时候动态插在类里面就可以了。此方案常用来实现@dynamic 属性,比如要访问CoreData框架中NSManagedObjects对象的属性时就可用这么做,因为实现这些属性所需要的存取方法在编译器就能确定

2.2.1 备援接受者

    备援接受者为处理未知的选择子提供第二次机会,嫩故能把这条消息转给其他接受者来处理。该步骤对应的处理方法如下:

-(id)forwardingTargetForSelector:(SEL)selector

方法参数代码未知的选择子,若当前接受者能找到备援对象,则将其返回,若找不到,就返回nil。通过次方案,我们可以用“组合”来模拟“多重继承”的某些特性。在一个对象内部,可能还有一系列其他对象,该对象可经由此方法将能够处理某选择子的相关内部对象返回,从外界看来,好像是该对象亲自处理这些消息。若是想在发送给备援接受者之前先修改消息内容,那就通过完整消息转发机制来做。

2.2.2 完整的消息转发

    如果转发算法到了这一步,那么唯一能做的就是启用完整的消息转发机制,首先创建NSInvocation对象,把尚未处理的那条消息有关的全部细节都封于其中。此对象包含选择子,目标及参数。在触发NSInvocation对象时,“消息派发系统”将会把消息指派给目标对象。

此步骤会调用下列方法来转发消息:

-(void)forwardInvocation:(NSInvocation *)invocation

    该方法实现简单,只需要改变调用目标,使消息在新目标上得以调用即可。然而这样实现出来的方法与“备援接受者”方案所实现的方法等效,所有很少有人采用这么简单的实现方式。比较有用的实现方式为:在触发消息前,先以某种方式改变消息内容,比如追加另外一个参数,或是改变选择子。

    实现该方法时,若发现某调用操作不应由本类处理,则需要调用超类的同名方法。这样集成体系中的某个类都有机会处理此方法调用,直到NSObject,继而调用”doesNotRecognizeSelector:”以抛出异常,此异常表明选择子最终未能得到处理。

三 消息转发全流程

    接受者在每一步中均有机会处理信息。步骤越往后,处理消息的代价就越大,最好能在第一部就能处理完,这样,运行期系统就可以将方法缓存起来,如果这个类的实例稍后收到同名选择子,就武器启动消息转发流程。若想在第三部把消息转给备援接受者,还不如提前到第二步,因为第三步只是修改了调用目标,这项改动放在第二步执行更为简单,而且不用创建并处理完整的NSInvocation

四 总结

  • 若对象无法响应某个选择子,则进入消息转发机制
  • 通过运行期的 动态方法解析 功能,可以在需要用到某个方法时再将其加入类中
  • 对象可以把其无法解读的某些选择子转交给其他对象来处理(备援接受者\完整的消息转发)
  • 经过上述两步之后,如果还是没办法处理选择子,那就启动完整的消息转发机制

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • ios OC 消息转发机制

    在编译期向类发送了其无法解读的的消息并不会报错,因为在运行期可以继续让类中添加方法,所有编译器在编译时还无法确知类中到底会不会有某个方法实现,当对象接收到无法解...

    conanma
  • OC 消息机制及转发

    这个错误提示几乎每个开发者都会遇到很多次,是由于给对象发送了一个无法识别的消息造成系统不能正常处理。

    Light413
  • iOS进阶之消息转发机制

    Dwyane
  • 深入理解iOS消息转发机制

    程序员不务正业
  • (4)OC中消息和消息转发-02

    czjwarrior
  • (3)OC中消息和消息转发-01

    czjwarrior
  • iOS消息机制

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++...

    周希
  • 【iOS】运行时消息传递与转发机制

    Objective-C是一门非常动态的语言,以至于确定调用哪个方法被推迟到了运行时,而非编译时。与之相反,C语言使用静态绑定,也就是说,在编译期就能决定程序运行...

    VV木公子
  • Runtime消息转发机制

    Class_Nonnull isa OBJC_ISA_AVAILABILITY;

    ZY_FlyWay
  • Runtime 中的消息机制

    说道Objective-C里面的消息机制,大部分人都知道是调用方法其实就是发送消息,一个叫objc_msgSend的东西负责的。今天结合《编写高质量iOS与OS...

    李海彬
  • 理解消息转发机制

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

    王大锤
  • iOS运行时Runtime基础

    梧雨北辰
  • iOS消息机制相关

    OC的函数调用都是通过objc_msgSend进行消息发送来实现,相对于C/C++来说,操作空指针引起crash问题,objc_msgSend通过判断self来...

    我只不过是出来写写代码
  • iOS引入JavaScriptCore引擎框架(二)

    为何放弃第一种方案 UIWebView的JSContext获取     上篇中,我们通过简单的kvc获取UIWebVIew的JSContext,但是实际上,ap...

    欲休
  • Runtime系列(一)-- 基础知识

    众所周知,Objective-C 是一种运行时语言。运行时怎么来体现的呢?比如一个对象的类型确定,或者对象的方法实现的绑定都是推迟到软件的运行时才能确定的。而运...

    Haley_Wong
  • app中的webview通识篇(上)

    如果你还是第一次与app合作开发webview的页面,那么对于如何调试,可能有哪些问题可能是不够了解的。本文尝试性的根据自己的经验给大家一个入门级别的了解,如果...

    RobinsonZhang
  • 判断js引擎是javascriptCore或者v8

    来由   纯粹的无聊,一直在搜索JavaScriptCore和SpiderMonkey的一些信息,却无意中学习了如何在ios的UIWebView中判断其js解析...

    欲休
  • Phonegap 之 iOS银联在线支付(js调用ios端银联支付控件)

      Phonegap项目,做支付的时候,当把网站打包到ios或android端成app后,在app上通过wap调用银联在线存在一个问题:

    tandaxia

扫码关注云+社区

领取腾讯云代金券