ObjC Runtime简析

栏目: Objective-C · 发布时间: 5年前

内容简介:在iPhone cpu 使用arm64架构之前,isa指针就是一个Class类型的普通指针,存储着Class、Meta-Class的内存地址。在这之后apple对isa指针进行了优化,利用位域的技术,将isa指针换成了一个union(共用体)。arm64架构之后的isa指针每一位都存储着不同的信息,在isa的union中有一个结构体表示了每一位对应的含义。在runtime源码中class的定义为:其中我们可以看到通过bits的

在iPhone cpu 使用arm64架构之前,isa指针就是一个Class类型的普通指针,存储着Class、Meta-Class的内存地址。在这之后apple对isa指针进行了优化,利用位域的技术,将isa指针换成了一个union(共用体)。arm64架构之后的isa指针每一位都存储着不同的信息,在isa的union中有一个结构体表示了每一位对应的含义。

ObjC Runtime简析

Class

在runtime源码中class的定义为:

ObjC Runtime简析

其中我们可以看到通过bits的 data() 函数可以获取到一个 class_rw_t 的结构体指针。 class_rw_t 结构体中存放着我们熟悉的东西:方法列表、属性列表和协议列表等。除此之外还有一个 class_ro_t 的结构体指针,它指向的结构体拥有与 class_rw_t 结构体类似的结构,也存放有方法列表、协议列表,初次之外还有成员变量列表等数据。

通过 class_rw_tclass_ro_t 的名字我们可以看出,rw代表的是可读可写的结构,而ro则代表只读的结构。

总体上说class的结构可以用下图表示

ObjC Runtime简析

class_rw_t 中方法列表、属性列表、协议列表都是 xxx_array_t 二维数组,而 class_ro_t 中的方法列表,协议列表等都是 xxx_list_t 的一维数组。 class_rw_t 中的二维数组中的存放的就是许多 xxx_list_t 的一维数组。这些一维数组可能是来自原始类( class_ro_t 中存放的是类的原始的信息),也可能是来自category。

method_t

对于methodlist而言,一个方法就是 method_list_t 的一个元素,其关系可以用下图表示:

ObjC Runtime简析

也就是说 method_t 才方法列表中存储的最小元素。method_t的是一个结构,它是对方法/函数的封装。

ObjC Runtime简析

method_t 有方法名称(name)、返回值类型和参数类型的编码(types)、指向函数的指针(imp)。

name

name 就是方法的名称,它是 SEL 类型的。 SEL 就是selector是方法选择器,它是根据方法名字生成的,本质上就是一个字符串,跟方法存放的位置无关。也就是说不同类中相同名字的方法的方法选择器是一样的。

获取 SEL 的方法可以使用 @selector() 或者runtime api中的 sel_registerName() 获得。使用 sel_getName() 或者 NSStringFromSelector() 将其转换为字符串。

types

types 包含了函数返回值和参数编码的字符串。它就是一个字符串,将函数返回值类型和参数类型按照一定的编码规则生成的一个字符串。可以使用 @encode() 将具体类型表示成字符串编码。

apple提供的编码规则如下:

ObjC Runtime简析

imp

imp在runtime中的定义如下:

ObjC Runtime简析

正如其注释所说:这是一个指向方法实现的函数指针。

方法缓存

我们知道平时我们进行方法调用的时候不可能一直按照从isa指针开查找方法的规则来查找方法的实现的。runtime定义的类中有一个方法缓存,这里面缓存了调用过的方法。当我们调用方法的时候runtime会首先从缓存中查找有没有方法的实现被缓存过。如若有,则直接通过缓存取出方法进行调用,如果没有则再按照isa指针的流程进行方法实现的查找。

ObjC Runtime简析

方法缓存是使用散列表实现的。SEL作为散列表的key,IMP和SEL作为散列表的value。

通过上图我们也可以看出 _buckets 是一个数组,数组中存放了方法缓存的散列表。那么是如何从方法缓存中取出方法来的呢?如果是遍历查找的话,效率是非常低的,apple利用了一种算法,它利用 @selector(method_name) 和mask(buckets的长度减一)进行一次按位与运算得出一个下标,然后将方法缓存存放到这个下标对应的位置,同样取缓存的时候也是进行了这样一次操作。这样一来效率就提高了,但是整个数组中会出现一些没有用到的空位置,所以这是一种利用空间来换时间的算法。

ObjC Runtime简析

END

本篇简单的介绍了Runtime中关于isa、class、以及方法缓存的相关问题。下篇介绍obj方法调用的相关问题。


以上所述就是小编给大家介绍的《ObjC Runtime简析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

黑客秘笈

黑客秘笈

[美]彼得·基姆 / 徐文博、成明遥 / 人民邮电出版社 / 2015-7-1 / 45.00

所谓的渗透测试,就是借助各种漏洞扫描工具,通过模拟黑客的攻击方法,来对网络安全进行评估。 本书采用大量真实案例和集邮帮助的建议讲解了在渗透测试期间会面临的一些障碍,以及相应的解决方法。本书共分为10章,其内容涵盖了本书所涉的攻击机器/工具的安装配置,网络扫描,漏洞利用,人工地查找和搜索Web应用程序的漏洞,攻陷系统后如何获取更重要的信息,社工方面的技巧,物理访问攻击,规避杀毒软件的方法,破解......一起来看看 《黑客秘笈》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

SHA 加密
SHA 加密

SHA 加密工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具