对Objective-C的runtime的一些理解

首先copy某位博主的写的一段关于runtime的介绍:

runtime是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API。 
在我们平时编写的OC代码中, 程序运行过程时, 其实最终都是转成了runtime的C语言代码, runtime算是OC的幕后工作者 。

这算是从技术层介绍了runtime,下面我结合阅读官方文档谈谈自己对runtime的理解:

简要介绍

因为OC会尽可能多的把事情从编译时、连接时延迟到运行时来做,所以它还需要一个运行时的系统来执行编译好的代码(因为只执行编译好的代码还没有做完应该做的事,这些事需要在运行时来做),这个运行时的系统,就是OC的runtime。

消息

objc_msgSend函数

OC与其他语言不同的的一点就是OC中的函数调用是采用了消息发送的机制,但是直到程序运行之前,消息都没有与任何方法实现绑定起来。只有在真正运行的时候才会根据函数的名字来确定应该调用的函数。

在OC中,消息表达式会被转化为objc_msgSend函数调用。比如

[receiver message]

就将被转化为

objc_msgSend(receiver,selector,arg1,arg2,...)

这个函数为动态绑定做了所有需要做的事

  • 函数首先找到选择器(selector)提到的方法实现。因为这个函数是通过receiver的类来精确的找到方法的实现,所以不同的类中有相同的方法是对寻找过程没有影响的。
  • 接着函数调用找到的方法实现,并把接受对象(一个指向这个对象数据指针)和参数都传递给那个方法
  • 最终把方法实现传递过来的返回值作为自己的返回值

消息传递的关键在于编译器为每个类和对象构建的结构。每一个类都包括下面两个必须的因素:

  • 一个指向它父类的指针
  • 一个类分派表。这个表将方法选择器与方法在类具体的地址关联起来。eg.setOrigin方法的选择器将被与setOrigin::(方法实现代码)的地址关联起来。

isa指针
当创建一个新对象时,会为它分配一段内存,这个对象的实例变量也会被初始化。在这个对象的变量中第一个就是一个一个纸箱它的类的指针(isa)。通过这个指针一个对象可以访问它的类,并通过它的类来访问该类继承的所有类。

下图是类和对象的结构因素
Messaging Framework

当消息传递函数(ojc_msgSend)被传送到一个对象时,消息传递函数由对象的isa指针来得到该对象的类并在这个类里的分派表里训中相应的消息选择器。如果找不到相应的选择器,objc_msgSend函数由该类指向其父类的指针得到其父类,并在父类的分派表中寻找是否有相应的选择器,如此继续,直到回溯到NSObject类。一旦找到相应的选择器,objc_msgSend函数通过分派表调用与选择器对应的函数,并执行相应的函数。

这就是在运行时选择方法实现的方式,用面向对象语言来说,这个方法是被动态绑定到消息了。

为了提高消息传递的速度,runtime系统缓存了它使用过的选择器和方法的地址。每一个类都有一个独立的缓存,这个缓存可以包含自己类的方法,也可以包含继承类的方法。在从分派表搜索之前,消息传递函数首先检查接受对象的缓存。

总结一下消息发送之后是怎么来动态查找相对应的方法

首先,编译器将代码[receiver message];转化为objc_msgSend(receiver, @selector (message));,在objc_msgSend函数中。首先通过obj的isa指针找到obj对应的class。在Class中先去cache中 通过SEL查找对应函数method,若 cache中未找到。再去类的分派表中查找,若分派表中未找到,则取superClass中查找,如此一致回溯至NSObject类。若能找到,则将method加入到cache中,以方便下次查找,并跳转到对应的函数中去执行。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值