前言
熟练的运用Runtime相关的技术,能够更好的解决复杂问题和实现复杂需求
类在runtime中的表示
//类在runtime中的表示 struct objc_class { // 实例的isa指向类对象,类对象的isa指向元类 Class isa;//指针,顾名思义,表示是一个什么 #if !__OBJC2__ Class super_class; //指向父类 const char *name; //类名 long version; long info; long instance_size struct objc_ivar_list *ivars //成员变量列表 struct objc_method_list **methodLists; //方法列表 struct objc_cache *cache;//缓存 // 调用过的方法存入缓存列表,下次调用先找缓存(优化) struct objc_protocol_list *protocols //协议列表 #endif } OBJC2_UNAVAILABLE;
API介绍
objc系列函数
例如类与协议的空间分配、注册、注销等操作
函数 | 函数作用 |
objc_getClass | 获取Class对象 |
objc_getMetaClass | 获取MetaClass对象 |
objc_allocateClassPair | 分配空间,创建类 |
objc_registerClassPair | 注册一个类 |
objc_disposeClassPair | 注销某个类 |
objc_allocateProtocol | 开辟空间创建协议 |
objc_registerProtocol | 注册一个协议 |
objc_setAssociatedObject | 为实例对象关联对象 |
objc_getAssociatedObject | 获取实例对象的关联对象 |
objc_removeAssociatedObjects | 清空实例对象的所有关联对象 |
objc_getProtocol | 获取某个协议 |
objc_copyProtocolList | 拷贝在运行时中注册过的协议列表 |
class系列函数
例如实例变量、方法、属性、协议等相关问题
函数 | 函数作用 |
class_addIvar | 为类添加实例变量 |
class_addProperty | 为类添加属性 |
class_addMethod | 为类添加方法 |
class_addProtocol | 为类遵循协议 |
class_replaceMethod | 替换类某方法的实现 |
class_getName | 获取类名 |
class_isMetaClass | 判断是否为元类 |
class_getSuperclass | 获取某类的父类 |
class_setSuperclass | 设置某类的父类 |
class_getProperty | 获取某类的属性 |
class_getInstanceVariable | 获取实例变量 |
class_getClassVariable | 获取类变量 |
class_getInstanceMethod | 获取实例方法 |
class_getClassMethod | 获取类方法 |
class_getMethodImplementation | 获取方法的实现 |
class_getInstanceSize | 获取类的实例的大小 |
class_respondsToSelector | 判断类是否实现某方法 |
class_conformsToProtocol | 判断类是否遵循某协议 |
class_createInstance | 创建类的实例 |
class_copyIvarList | 拷贝类的实例变量列表 |
class_copyMethodList | 拷贝类的方法列表 |
class_copyProtocolList | 拷贝类遵循的协议列表 |
class_copyPropertyList | 拷贝类的属性列表 |
object系列函数
例如实例变量
函数 | 函数作用 |
object_getClassName | 获取对象的类名 |
object_getClass | 获取对象的Class |
object_setClass | 设置对象的Class |
object_getIvar | 获取对象中实例变量的值 |
object_setIvar | 设置对象中实例变量的值 |
object_getInstanceVariable | 获取对象中实例变量的值 (ARC中无效,使用object_getIvar) |
object_setInstanceVariable | 设置对象中实例变量的值 (ARC中无效,使用object_setIvar) |
method系列函数
例如方法的参数及返回值类型和方法的实现
函数 | 函数作用 |
method_getName | 获取方法名 |
method_getImplementation | 获取方法的实现 |
method_getTypeEncoding | 获取方法的类型编码 |
method_getNumberOfArguments | 获取方法的参数个数 |
method_copyReturnType | 拷贝方法的返回类型 |
method_getReturnType | 获取方法的返回类型 |
method_copyArgumentType | 拷贝方法的参数类型 |
method_getArgumentType | 获取方法的参数类型 |
method_getDescription | 获取方法的描述 |
method_setImplementation | 设置方法的实现 |
method_exchangeImplementations | 替换方法的实现 |
property系列函数
如属性名、属性的特性等
函数 | 函数作用 |
property_getName | 获取属性名 |
property_getAttributes | 获取属性的特性列表 |
property_copyAttributeList | 拷贝属性的特性列表 |
property_copyAttributeValue | 拷贝属性中某特性的值 |
protocol系列函数
如获取协议名称、是否遵循协议等
函数 | 函数作用 |
protocol_conformsToProtocol | 判断一个协议是否遵循另一个协议 |
protocol_isEqual | 判断两个协议是否一致 |
protocol_getName | 获取协议名称 |
protocol_copyPropertyList | 拷贝协议的属性列表 |
protocol_copyProtocolList | 拷贝某协议所遵循的协议列表 |
protocol_copyMethodDescriptionList | 拷贝协议的方法列表 |
protocol_addProtocol | 为一个协议遵循另一协议 |
protocol_addProperty | 为协议添加属性 |
protocol_getProperty | 获取协议中的某个属性 |
protocol_addMethodDescription | 为协议添加方法描述 |
protocol_getMethodDescription | 获取协议中某方法的描述 |
ivar系列函数
函数 | 函数作用 |
ivar_getName | 获取Ivar名称 |
ivar_getTypeEncoding | 获取类型编码 |
ivar_getOffset | 获取偏移量 |
sel系列函数
函数 | 函数作用 |
sel_getName | 获取名称 |
sel_getUid | 注册方法 |
sel_registerName | 注册方法 |
sel_isEqual | 判断方法是否相等 |
imp系列函数
函数 | 函数作用 |
imp_implementationWithBlock | 通过代码块创建IMP |
imp_getBlock | 获取函数指针中的代码块 |
imp_removeBlock | 移除IMP中的代码块 |
Runtime实战使用
获取列表
/// 描述类中的一个方法 typedef struct objc_method *Method; /// 实例变量 typedef struct objc_ivar *Ivar; /// 类别Category typedef struct objc_category *Category; /// 类中声明的属性 typedef struct objc_property *objc_property_t;
有时候会有这样的需求,我们需要知道当前类中每个属性的名字(比如字典转模型,字典的Key和模型对象的属性名字不匹配)
我们可以通过runtime的一系列方法获取类的一些信息
属性列表
方法列表
成员变量列表
遵循的协议列表