runtime整体数据结构
objc_object
我们平时用的所有对象都是id类型的,在runtime中,id 就是 objc_object结构体
包含:
- isa_t共用体
- isa操作:通过结构体,来获取isa所指向的类对象,或者通过通过类对象的isa指针获取它的元类对象
- 弱引用相关:标记一个对象是否曾经有过弱引用指针
- 我们为对象设置了关联属性,关于关联属性的一些相关方法
- MRC下经常用到的runtain,release等方法实现
以上均封装在objc_object结构体中
objc_class
OC中的Class,代表一个类,他在runtime中对应objc_class结构体
objc_class继承objc_object
所以Class也是一个对象,类对象,因为它继承自objc_object
包含:
- superClass指针,指向class类型,我们平时说的类与父类,实际上是通过objc_class中superClass成员变量来定义的
- cache成员变量: 方法缓存结构,消息传递时会使用
- bits数据结构: 关于类所定义的变量,属性,方法都在bits中
isa指针
它是C++中的共用体,在OC中名称是isa_t
不论是64位架构上,共用体是64个0或者1的数字
分两种类型:
- 指针型isa: 64位的0或者1的整体内容代表所指向的Class的地址,也就是可以通过isa的内容来获得类对象的地址
- 非指针型isa: isa的值得部分代表Class的地址,之所以这样是因为我们在寻址过程中,只有三四十位数就可以保证我们寻找到所有Class地址了,多出来的位可以用来存储其他相关内容,来达到节省内存的目的
isa的指向
关于对象,它指向类对象
例如我们拥有一个实例,实例就是OC中对应的id类型,在Runtime中就是objc_object,里面有个isa指针,会指向它对应的Class
关于类对象,指向元类对象
class因为集成objc_object,所以里面也有isa指针,指向其元类对象
当我们进行方法调用时,调用一个实例的实例方法,实际上是通过isa指针,到它的类对象中,去进行方法查找
如果我们调用的是类方法,那么是通过类对象的isa指针,到它的元类对象中去查找
cache_t
- 是用于快速查找方法执行函数的一个结构
当我们调用一个方法时,如果有缓存,我们就不需要去方法列表中遍历了,可以提高方法调用速度
是可增量扩展的哈希表结构
当结构存储量增大的过程中, cache_t会增量扩大它的内存空间来支持更多的缓存,用哈希表实现这个数据结构,是为了提高查找效率cache_t数据结构是计算机局部性原理的最佳应用
在一般调用方法时,有几个方法调用频次较高,把他们放到方法缓存中,下次的命中率就会更高
cache_t具体数据结构说明
可以理解为是数组来实现的
每个对象都是bucket_t这样的一个结构体, bucket_t有两个主要成员变量,key和IMP
key对应OC中的selector,在调用方法时是个选择器SEL
IMP理解为无类型的函数指针
可以通过方法选择器的名称key来寻找这个方法的具体实现IMP
假如现在有个key,可以通过哈希查找算法来定位当前key所对应的bucket_t位于数组当中哪个位置,然后从这个位置中提取出bucket_t中的IMP
class_data_bits_t
这个结构是objc_class中的成员结构
class_data_bits_t主要是对class_rw_t的封装
class_rw_t代表了类相关的读写信息,例如给类添加的分类的一些方法,属性以及协议等,同时它也对class_ro_t的封装,我们可以随时创建分类,为类增加属性或者方法
rw是readWrite的简写
ro是readOnly的意思,创建类时,添加的成员变量或方法列表在之后就没办法修改了class_ro_t代表了类相关的只读信息
class_rw_t
包含
- class_ro_t
- protocols类分类中的协议
- properties类分类中的属性
- methods类分类中的方法
这三个数据结构是个二维数组
假如我们添加了分类A,分类A中的所有方法都在第一列竖列表中,存在二维数组的第一项
又添加了分类B,分类B中的所有方法都在第二列竖列表中,存在二维数组的第二项
class_ro_t
1.类名
2.声明的类的成员变量
3.类的属性
4.类的协议
5.类的方法列表
除1外都是一维数组
在方法列表当中存储的内容,一般是分类中添加的方法
method_t实际上是对方法的抽象说明
method_t
是对函数四要素的封装
函数四要素决定了函数的唯一性
method_t是个结构体,主要有三个数据类型
- name 函数名称
- types 函数返回值和参数的集合
- imp 无类型的函数指针,对应着函数体
types是如何表示返回值和参数的
苹果的Type Encodings技术
types成员属性,实际上表达结构是:
第一个位置永远是函数的返回值类型,后面跟着每个参数的参数类型
参数可以有多个,返回值只有一个
V@:代表types所存储的内容
V对应返回值,@对应参数1,:对应参数2