1.runtime
属于OC底层,为OC的动态性提供支持,是一套C语言的api,封装了很多动态性相关的函数。编译时还不能真正决定调用哪个函数,在程序运行时,才最终转成了相关的c语言api进行调用。
class,类,由编译器创造的,结构体包括包括isa指针、指向父类的isa指针、变量列表、方法列表、协议列表等等信息。
class_ro_t,成员变量,方法和协议等在编译时已经确定,我们添加的方法是通过class_rw_t实现的。首先加载objc_class和class_ro_t,当类被首次调用时,创建class_rw_t,有动态添加方法时创建class_rw_ext_t;
实例对象(Object)是我们对类对象alloc或者new操作时所创建的,在这个过程中会拷贝实例所属的类的成员变量,但并不拷贝类定义的方法。调用实例方法时,系统会根据实例的isa指针去类的方法列表及父类的方法列表中寻找与消息对应的selector指向的方法。
isa指针,通过isa指针可以找到它所在的类。实例对象去找类对象的信息,类对象去找元类对象的信息。
SEL:方法编号;IMP:函数指针,保存了方法的地址;Method:IMP,SEL,类型指定字符串;
指向:实例对象通过isa指针指向类对象,类对象的指向元类对象,元类对象指向根元类对象。
load:当程序启动时候就会调用,整个程序运行中只会调用一次,在类加载到内存时调用,在runtime加载类、分类时调用,按照编译先后顺序调用(先编译,先调用),调用顺序:父类->子类->分类;如果使用不好,容易影响启动速度,所以要避免耗时操作;
initlialize:当类第一次被调用的时候就会调用,通过objc_msgSend(obj,@selector()))调用,调用顺序:分类->子类->父类;
2.相关应用
a、动态创建类
kvo底层原理:给对象添加kvo监听,动态生成子类,让isa指针指向子类,在调用父类的setter方法前后调用willChangeValueForKey:和didChangeValuefForKey:方法,当调用时候会触发observeValueForKeyPathofObject:change:context:,直接修改实例变量是不会触发的。当移除观察者后,会删除子类。
b、利用关联对象给分类添加属性
添加类
利用分类添加属性
c、遍历类的所有成员变量,objc_setAssociatedObject添加的属性不在这
d、交换方法
e、利用消息转发机制解决方法找不到的异常问题
3.实际应用
消息转发机制,字典转model,分类中添加属性,埋点,kvo,归档解档