Runtime

192 阅读2分钟

简介

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. 模型嵌套模型;模型嵌套数组