OC学习Runtime之消息传递,消息转发机制

坚持 成长 每日一篇

相关类和函数

介绍消息发送机制之前介绍一下会用到的几个相关类和函数

NSMethodSignature(方法签名)

方法签名:用语记录一个方法的参数和返回值类型的类。类似于objc_method_description结构体。方法签名是用于初始化NSInvocation用的。

NSInvocation

用于记录一个消息(方法)的接收者(target)方法名(SEL)参数类型,参数等信息,包含执行该消息方法的类。
此类类似于结构体Method。
他提供了- (void)invokeWithTarget:(id)target;调用对象中的方法。类似于id method_invoke(id receiver, Method m, …) 函数。

注意:NSMethodSignature,NSInvocation一般我们都是用语消息转发时候用到。正常我们用的比较少。

objc_msgSend 函数

objc_msgSend函数负责像某对象发送一个消息。定义如下

id objc_msgSend(id self, SEL op, ...)

在OC里面我们调用对象方法[Receiver message]的这种模式,实际是通过调用objc_msgSend(Receiver,message,…)函数来找到方法的实现入口。objc_msgSend实现原理是通过对象对应的objc_object的ISA找到该类对应的objc_class结构体。通过依次遍历objc_cache,objc_method_list里面的方法找到方法实际入口,如果没有找到,则跳到父类寻找,以此类推如果最终都没有找到就会发生下面介绍的消息转发机制。

消息转发机制

Runtime中方法的动态绑定让我们写代码时更具灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一个方法的实现等。不过灵活性的提 升也带来了性能上的一些损耗。毕竟我们需要去查找方法的实现,而不像函数调用来得那么直接。当然,方法的缓存一定程度上解决了这一问题。

特别是当我们需要在一个循环内频繁地调用一个特定的方法时,通过这种直接调用IMP减少查找过程的方式可以提高程序的性能。NSObject类提供了methodForSelector:方法,让我们可以获取到方法的指针,然后通过这个指针来调用实现代码。我们需要将methodForSelector:返回的指针转换为合适的函数类型,函数参数和返回值都需要匹配上。

当我们像一个对象发送消息[Receiver message],Receiver没有实现该消息,即[Receiver respondsToSelector:SEL]返回为NO情况下,其实系统不会立刻出现cash,这时Runtime system会对message进行转发。转发之后,如果该消息依然没有被执行就会出现Cash!Runtime System为我们提供了三种解决这种给对象发送没有实现消息方案。
消息转发机制基本上分为三个步骤:
1. 动态方法解析
2. 备用接收者
3. 完整转发
我们可以通过控制这三个步骤其中一环来解决这一个问题

特别注意:如果是正常类的消息,是不会走到这三个步骤的。所以走到这三个不步骤的前提条件已经确定该消息为未知消息

测试用例用到的源码
Boy.h


#import <Foundation/Foundation.h>

@interface Boy : NSObject
-(void)say:(NSString*)str girl:(NSString*)girl;
@end

Boy.m

#import "Boy.h"
#import "Girl.h"
@implementation Boy
-(void)say:(NSString*)str girl:(NSString*)girl
{
    NSLog(@"%@",str);
    NSLog(@"
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值