简介
Runtime是一套底层纯C语言API,OC代码最终都会被编译器转化为运行时代码,通过消息机制决定函数调用方式,这也是OC作为动态语言使用的基础
消息机制的基本原理
OC方法调用,编译阶段确定了向哪个接收者发生message消息,但接收者如何响应取决于运行时的判断
objc_msgSend
编译阶段,OC方法调用[receiver selector]被编译器转化为C函数objc_msgSend
解析过程
1. 重写resolveInstanceMethod或resolveClassMethod方法,添加方法实现
2. 重写forwardingTargetForSelector方法,指定其他对象接收这个消息
3. 重写forwardInvocation方法,可以将消息转发给多个对象
4. 若仍然无法响应,则报错找不到响应方法,系统抛出doesNotRecognizeSelector消息
应用
动态添加方法实现
Runtime足够强大,能够在运行时动态添加一个未实现的方法,这个功能主要有两个应用场景:
1. 动态添加未实现方法,解决代码中因为方法未找到而报错的问题
2. 利用懒加载思路,若一个类有很多个方法,同时加载到内存中会耗费资源,可以使用动态解析添加方法
动态方法交换(Method Swizzling)
通过Runtime获取方法实现的地址,进而动态地交换两个方法
1. 交换两个自定义方法
2. 拦截并替换系统方法
// 获取类方法的Method
Method _Nullable class_getClassMethod(Class _Nullable cls, SEL _Nonnull name)
// 获取实例对象方法的Method
Method _Nullable class_getInstanceMethod(Class _Nullable cls, SEL _Nonnull name)
// 交换两个方法的实现
void method_exchangeImplementations(Method _Nonnull m1, Method _Nonnull m2)
Category添加新的属性
给对象设置关联属性 objc_setAssociatedObject
通过key获取关联的属性 objc_getAssociatedObject
移除对象所关联的属性 objc_removeAssociatedObjects
运行时为category添加新的方法
解决同一方法高频率调用的效率问题
Runtime源码中的IMP作为函数指针,指向方法的实现。通过它,可以绕开发送消息的过程来提高函数调用的效率。当需要持续大量重复调用某个方法的时候,会十分有用
修改私有属性
获取属性列表并遍历,匹配到后修改
改进归档和解档
在归档和解档过程中,若一个Model有多个属性,对每个属性一一处理,会非常繁琐。可以获取属性列表,遍历处理
字典转模型
1. 获取属性列表
2. 遍历属性列表,以获取到的属性名为key,在JSON字典中寻找对应的值value
3. 再将每一个对应Value赋值给模型
需要解决的问题
1. 字典中的key与属性名不匹配;字典中key的数量和属性数量不一致
2. 模型嵌套模型;模型嵌套数组