Runtime 基础知识
- 数据结构
- 类对象与元类对象
- 消息传递机制
- 方法缓存
- 消息转发
- Method-Swizzling
- 动态添加方法
- 动态方法解析
基础数据结构
- objc_object
- objc_class
- isa指针
- method_t
objc_object
- 我们在OC中使用的所有的对象都是id类型的。id类型的对象对应到runtime当中就是 id == objc_object,就是objc_object 这样的一个结构体
- objc_object 数据结构
- isa_t 共用体 。
- 关于isa操作相关的方法 例如:通过objc_object这个结构来获取isa所指向的类对象。 类对象通过isa指针指向它的元类对象
- 弱引用相关的方法 这个结构是否曾经有过弱引用指针
- 关联对象相关方法 给这个对象设置类一些关联属性等,关联属性的相关方法也体现在objc_object这个结构体当中。
- 内存管理相关的一些方法实现 包括 retain、release、mrc、arc等这些方法实现都是封装在objc_object这个结构体当中。
objc_class
- Class == objc_class
- Class 代表的是一个类,对应的就是objc_class , class 就是一个对象,因为objc_class 继承字objc_class
- objc_class Class superClass Class类型的superClass 就是类对象的父类 ,通过superClass这个成员变量来实现的
- cache_t cache 缓存 成员变量
- class_data_bits bits 数据结构 , 在类中定义的变量、属性、方法都是存储在bits 这个成员结构中
isa指针
- 共用体 isa_t 是C/C++中的共用体 在OC中定义了 isa_t 这样的一个名称
如果是64位机器就是64个0. - 指针型isa -> isa的值代表Class的地址 比如我们使用objc_object这个对象的时候,可以通过isa的内容,来获取它类对象的地址
- 非指针型的isa -> isa的值的部分代表Class的地址 比如64位架构 可能有32位或者40位用来存放Class的地址,因为在寻址的过程中就能够找到Class的地址,多出来的这些位数可以用来存储其他的相关内容来达到节省内存的目的
- 这也就是产生两种类型的isa的原因
isa指针是什么含义
- 指针型isa
- 非指针型的isa
isa的指向
- 对象 -> 类对象
- 比如一个实例 在runtime中就是objc_object 中有 isa指针 -> Class
- 类对象 指向 元类对象
- Class 代表着 objc_class 继承自 objc_object所以Class也是一种对象,它的isa指向Metaclass元类对象
- 当我们调用一个isa指针的实例方法, 实际上是通过isa指针去它的类对象当中去查找
- 调用类对象的类方法实际是 通过类对象的isa指针去它的元类对象中去查找
cache_t
- 用于快速查找方法执行函数 比如在调用一个方法的时候如果有一个缓存就不用每次都到方法列表中逐一遍历去查找了。可以提高方法调用的速度或者是消息传递的速度
- 可增量扩展的哈希表结构 增量扩展: 当储存的量增大的时候会扩大其内存空间来支持更多的缓存 用哈希表来实现这个结构主要是为了提高查找效率
- 是局部性原理的最佳应用 通常调用的方法通常就那么几个,会把调用频率最高的方法缓存起来,下次命中率就会更高
bucket_t | bucket_t | bucket_t | bucket_t | … |
---|
- 数组结构 里面存放 bucket_t 这样的结构体
- bucket_t 里面有两个重要的成员变量 一个是key 另一个IMP
- key 对应OC语言里面的selector
- IMP 无类型的函数指针
- 根据 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的封装
- 给类添加的一些分类、方法、属性和协议 都是封装在class_rw_t 数据结构中 rw就是读写 ro 只读
- class_ro_t 代表了类相关的只读信息
class_rw_t
- methods 里面每个数据块都是一个数组,数组里面又有数组,这里面的单元就是method_t 这个数据结构
- 我们添加的分类A当中的所有的方法都放在第一个数组中
- 分类B同理
- Category 声明的方法在methods中
class_ro_t
- name 类名 我们可以通过反射来获取一个类的类名NSClassFromString
- ivars 声明定义的成员变量
- methodList 是本类中的方法 数据中类型为method_t