理解消息传递机制和消息转发机制

消息传递机制

在对象上传递方法叫做“传递消息”(pass a message)。消息有“名称”(name)或“选择子”(selector),可以接受参数,而且可能还有返回值。
在Object-c中,如果向对象传递消息,那就会使用动态绑定机制来决定需要调用的方法。在底层,所有方法都是普通的c语言函数,然而对象受到消息之后,究竟该调用哪个方法则完全于运行期决定,甚至可以在程序运行时改变。

id returnValue = [someObject messageName:parameter];

上述someObject是接受者(receiver),messageName是选择子(selector),选择子和参数合起来称为消息(message)。编译器看到此消息后,将其转换为一条标准的c语言函数调用,所调用的函数乃是消息传递机制中的核心函数:objc_msgSend。

void objc_msgSend(id self, SEL cmd, ...)

第一个参数代表接受者,第二个参数代表选择子,后续参数就是消息中的那些参数
编译器会把刚才的那个例子中的消息转换为如下函数:

id returnValue = objc_msgSend(someObject, @selector(messageName:),parameter);

objc_msgSend函数会依据接受者与选择子的类型来调用适当的方法。为来完成此操作,该方法需要在接受者所属的类中搜寻其“方法列表”。找到则跳到现实代码,否则,就沿着继承体系继续向上查找,如果还没有则执行消息转发操作。
对于其他的“边界情况”,则需要交由Objective-c运行环境的另一些函数来处理:

objc_msgSend_stret  //待发送的消息返回结构体时
objc_msgSend_fpret  //消息返回的事浮点型
objc_msgSendSuper   //如果要给超类发送消息

消息转发机制

当对象接受到无法解读的消息后,就会启动“消息转发”机制,程序员可由此过程高速对象应该如何处理未知消息。

消息转发分为两大阶段:
第一阶段先征询接受者,所属的类,看其是否能动态加方法,来处理当前这个“未知选择子”,这叫做动态方法解析
第二阶段涉及“完整的消息转发机制”。在第一阶段之后,接受者无法再动态新增方法去响应该选择子的消息了。那么在这个时候,接受者会看有没有其他对象能处理这条消息,若有则运行期系统会把消息转给那个对象。若没有,则启动完整的消息转发机制,将与消息有关的细节封装到NSInvocation对象中,再给接受者最后一次机会,令其设法解决当前还未处理的这条消息。

动态方法解析

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

+ (BOOL)resolveInstanceMethod:(SEL)selector
+ (BOOL)resolveClassMethod:(SEL)selector  //处理的是类方法

返回一个Boolean类型,表示这个类是否能新增一个实例方法以处理选择子。

使用这种办法的前提是:相关方法的实现代码已经写好,只等着运行的时候动态插在类里面就可以了。

备援接受者

当前接受者还有第二次机会能处理未知的选择子,在这一步中,运行期系统会问他:能不能把这条消息转给其他接受者来处理。与该步骤对应的处理方法如下:

- (id)forwardingTargetForSelector:(SEL)selector

方法参数代表选择子,若当前接受者能找到备援对象,则将其返回,若找不到,就返回nil。

注意:我们无法操作经由这一步所转发的消息。若是想在发送给备援接受者之前先修改消息内容,那就得通过完整的消息转发机制来做了。

完整的消息转发

如果转发算法已经来到这一步的话,那么唯一能做的就是启用完整的消息转发机制了。
首先创建NSInvocation对象,把与尚未处理的那条消息有关的全部细节都封于其中。消息派发系统将亲自出马,将消息指派给目标对象。此步骤会调用下列方法来转发消息:

- (void)forwardInvocation:(NSInvocation *)invocation

实现此方法时,若发现某调用操作不应由本类处理,则需要调用超类的同名方法。这样的话,继承体系中的每个类有机会处理此调用请求,直到最后抛出异常,表明选择子最终未能得到处理

消息转发全流程

resolveInstanceMethod -> forwardingTargetForSelectoer -> forwardInvocation ->消息未能处理。
接受者在每一步中均有机会处理消息。步骤越往后,处理消息的代价就越大。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值