Effective Objective-C 2.0 第二章 12、理解消息转发机制

详细分析请看我之前这篇文章:
iOS runtime 消息机制及消息转发。本篇对书中内容做简要介绍。

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

下面是整个消息转发流程图:

Effective Objective-C 2.0 第二章 12、理解消息转发机制_第1张图片
image

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

+ (BOOL) resolveInstanceMethod:(SEL)aSEL

这是第一次机会,我们可以在此处为未知消息新增一个处理方法。如果此处我们没有处理,则会调用以下方法:

- (id)forwardingTargetForSelector:(SEL)aSelector

这是第二次机会,交给其它类处理,可以将未知消息重定向给另一个拥有相同方法的对象。如果此处我们依然没有处理,则会调用:

- (void)forwardInvocation:(NSInvocation *)anInvocation

这里是最后一次机会。首先创建NSInvocation对象,把与尚未处理的那条消息有关的全部细节都封于其中。此对象包含选择子、目标(target)及参数。在触发NSInvocation对象时,“消息派发系统”(message-dispatch system)将亲自出马,把消息指派给目标对象。

最后这个方法可以实现得很简单:只需改变调用目标,使消息在新目标上得以调用即可。然而这样实现出来的方法与第二次机会方案所实现的方法等效,所以没必要在此方法中这么使用。比较有用的实现方式为:在触发消息前,先以某种方式改变消息内容,比如追加另外一个参数,或是改换选择子,等等。

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

总结

若对象无法响应某个选择子,则进入消息转发流程。

通过运行期的动态方法解析功能,我们可以在需要用到某个方法时再将其加入类中。

对象可以把其无法解读的某些选择子转交给其他对象来处理。

经过上述两步之后,如果还是没办法处理选择子,那就启动完整的消息转发机制。

你可能感兴趣的:(Effective Objective-C 2.0 第二章 12、理解消息转发机制)