1.Runtime数据结构相关
1.1 objc_object
Objective-C的面向对象都是基于C/C++的数据结构——结构体实现的。 我们平时使用的所有对象都是id类型,id类型对象对应到runtime中,就是objc_object结构体。
1.2 objc_class
Class指针用来指向一个 Objective-C 的类,它是objc_class结构体类型,所以class、meta-class底层结构都是objc_class结构体,objc_class继承自objc_object,所以它也有isa指针,它也是对象。
objc_class包含三个成员变量:superClasss指向当前类的父类,cache_t是用来提供消息传递过程中的缓存方法查找,class_data_bits_t是类的基本信息,如成员变量、属性、方法列表,包括通过分类所添加的成员、属性、 方法。
1.3 isa指针
isa指针用来维护对象和类之间的关系,并确保对象和类能够通过isa指针找到对应的方法、实例变量、属性、协议等。
它有指针型isa和非指针型的isa.指针型isa的值代表Class地址,非指针型isa值的部分代表Classs地址。
isa指向?
1.4 cache_t 是一个装满了bucket_t的Hash表。
用于快速查找方法执行函数;是可增量扩展的哈希表结构;是局部性原理的最佳应用。
1.5 class_data_bits_t
class_data_bits_t主要是对class_rw_t的封装
class_rw_t代表了类相关的读写信息、对class_ro_t的封装
class_ro_t代表了类相关的只读信息
1.6 method_t
Method就是method_t类型的指针。
method_t是对方法/函数的封装(函数四要素:函数名、返回值、参数、函数体)
Type Encodings
1.7 整体数据结构图
2.类对象与元类对象&消息传递相关
2.1 类对象和元类对象是什么?
类对象是存储实例方法列表等信息,元类对象存储类方法列表等信息。
2.2 打印出来的都是 Phone?
self class 转化成objc_msgSend方法,指的是当前对象。 super class 转化成objc_msgSendSupper方法,super里面包的receiver,也是当前对象,所以打印出来都是Phone。
2.2消息传递
消息传递过程:缓存是否命中? 当前类方法列表是否命中? 逐级父类方法列表是否命中?
3.方法缓存查找相关
3.1方法缓存查找的流程步骤?
根据给定的方法选择器SEL,通过哈希查找对应bucket_t中的方法实现IMP。
3.2 当前类中查找
对于已排序好的列表,采用二分查找算法查找方法对应执行函数。
对于没有排序的列表,采用一般遍历查找方法对应执行函数。
3.3 父类逐级查找
4.消息转发相关
4.1 消息转发流程是什么样的?
5.Method-Swizzling相关
6.动态添加方法相关
6.1 你是否使用过perforSelector:方法?
7.动态方法解析相关
7.1 是否使用过@dynamic 属性? 当我们用@dynamic修饰时,代表不需要编译器在编译时生成getter和settre方法的具体实现,而是在运行时具体的调用的时候再去为他添加具体实现。
动态运行时语言将函数决议推迟到运行时。编译时语言在编译期进行函数决议。
8.Runtime实战
8.1 [obj foo]和objc_msgSend()函数之间有什么关系?
编译器的处理过后,[obj foo]就转化成obj_msgSend()函数调用了,就开始了消息传递的过程。
8.2 runtime如何通过Selector找到对应的IMP地址的?
首先查找当前实例所对应类对象的缓存是否有selector的IMP实现,如果缓存命中就把缓存的函数返回给调用方,如果缓存没有命中,再根据当前类的方法列表去查找对应selector的IMP实现,当前类如果没有命中,再根据当前类的superClass指针逐级查找父类的方法列表。然后查找selector的IMP实现。
8.3 能否向编译后的类中增加实例变量?
不能,编译之前已经完成了实例变量的布局,class_ro_t ,readOnly,即编译后没有办法修改的。 如果是动态添加的类中,可以增加实例变量。