引言
1 | id returnValue = [object fun: parameter]; |
1 | id returnValue = objc_msgSend(object, @selector(fun:), parameter); |
消息转发(message forwarding)
在编译期间向某类发送了其无法解读的消息并不会报错,因为在运行期可以继续向类中添加方法,所以编译器在编译时还无法确认类中会不会有该方法的实现。当最终都没能解读此消息后,就会启动 消息转发(message forwarding)机制。如果经过消息转发阶段仍未找到对象执行解读此消息,结果则会调用“doesNotRecognizeSelector”方法抛出异常以程序崩溃而告终。不过开发者在编写自己的类时,可在消息转发阶段设置“挂钩”,用以执行预定的逻辑,而不至于应用程序崩溃。
消息转发阶段分为两大阶段:第一阶段会先征询接受者所属的类,看其是否为该方法动态添加了方法的实现部分,称为“动态方法解析”(dynamic method resolution);如果仍没解决问题会来到第二阶段,如果来到了该阶段,代表着接受者自己就无法再以动态新增方法的手段来响应该消息了。此时,运行期系统会请求接受者以其他手段来处理与消息相关的方法调用,又细分为两步:首先请接受者看有没有其他对象“备援的接受者”(replacement receiver)来处理这条消息,若存在,则把消息转发给那个对象,消息转发结束。若没有,则启动“完整的消息转发机制”(full forwarding mechanism),运行期系统会把与该消息有关所有的细节封装到 NSInvocation 对象中,再给接受者最后一次机会,令其设法解决当前还未处理的消息。1、动态方法解析(dynamic method resolution)
对象在收到无法解读的消息后,首先会调用其所属类的下列方法:
1 | +(BOOL)resolveInstanceMethod: (SEL)selector //方法类型为对象方法 |
1 | +(BOOL)resolveClassMethod: (SEL)selector //方法类型为类方法 |
/2.png)
2、备援接受者(replacement receiver)
该阶段当前接受者还有第二次机会处理这个未知的消息,会调用
1 | +(id)forwardingTargetForSelector: (SEL)selector |
/4.png)
3、完整的消息转发机制(full forwarding mechanism)
首先创建 NSInvocation 对象,把与尚未处理的那条消息有关的全部细节都封装在里面,这个对象包含方法、目标接受者及参数。 在触发 NSInvocation 对象时,“消息派发系统”(message-dispatch system)会调用1 | -(void)forwardingInvocation: (NSInvocation *)invocation |
/5.png)
总结
消息传递阶段:作为面向对象高级编程语言几乎都有与之相对应的函数调用轨迹。 消息转发阶段:接受者在每一步都有机会处理这个消息,只不过越往后,处理消息的代价就越大。“动态绑定”的机制为Object-C语言赋予了动态语言所拥有的特性,也因为此灵活性在代码执行速度上就不及“静态绑定”的函数调用操作那样迅速了,即使在类的内部缓存着曾经调用过的方法。消息转发全流程如下图:/6.jpg)
参考文献:
第二章:对象、消息、运行期


