消息转发的两大阶段
先征询接收者,所属的类,看其是否能够动态添加方法,以处理这个『未知的选择子』,这叫做动态方法解析
-
第一阶段执行完了,那么接收者自己就无法再以动态新增方法的手段来处响应包含改选择子的消息了。此时,运行期系统会请求接收者以其他手段来处理与消息相关的方法调用。又分为亮度
2.1 接收者看有没有其他的对象能够处理这条消息。如果有,就把消息转发给这个对象处理,然后消息转发过程结束。
2.2 若没有「备援的接收者」,则启动完整的消息转发机制运行期系统会把与消息有关的全部细节封装到 NSInvocation 对象中,在给接收者最后一次机会,令其设法解决当前还未处理的这条消息
动态方法解析
- 对象在收到无法解读的消息之后,首先会调用所属类的下列类方法:
+ (BOOL) resolveInstanceMethod:(SEL) selector;
//参数是那个未知的选择子,其返回值是 BOOL 表示这个类是否能够新增一个实例方法用以处理这个消息
//在继续往下执行转发机制之前,本类有机会新增一个处理此选择子的方法
//加入尚未实现的方法不是实例方法而是类方法,那么运行期系统就会调用 resoleClassMethod:
//使用这种方法的前提:相关的实现代码已经写好了,只等运行的时候动态插在类中就行了
备援接收者
当前接收者还有第二次机会处理未知的选择子。运行期系统会问他:能不能把这条消息交给其他的接收者来处理 对应的方法:
//方法参数代表未知的选择子,若当前接收者能找到备援对象,则将其返回。若找不到,就返回nil
- (id) forwardingTargetForSelector:(SEL) selector;
完整的消息转发
- 创建 NSInvocation 对象,把与尚未处理的那条消息有关的全部细节封装在这里面。包括 选择子、目标、参数。
- 在触发 NSInvocation 对象,「消息派发系统」将亲自出马,把消息指派给目标对象
//调用这个方法
- (void) forwardInvocation:(NSInvocation *) invocation;
- 这个方法实现起来很简单:只需改变调用目标 和 备援接收者 类型
- 还有一种实现方式:在触发消息前,先以某种方式改变消息内容,比如追加另外一个参数,或者是改变选择子,等等