runtime 概念
runtime 运行时机制,主要是消息机制。OC 中的方法调用属于消息的发送,动态调用过程,在编译时可以调用任何方法,即使这个方法并没有实现也不会报错,只有在真正运行的时候才会根据方法名找到对应的方法来调用。
oc 和 runtime
- runtime库里面包含了跟类,成员变量,方法相关的 api 函数,是一套比较底层的纯 C 语言 API,平时写 OC 代码,最后都是转成 runtime 的 c 语言代码。
// OC
[[Person alloc] init];
// runtime
objc_msgSend(objc_msgSend("Person","alloc"),"init")
runtime用来干什么的
- 程序运行过程中,动态创建一个类(KVO 的底层实现)
- 在程序运行中,动态地为某个类添加属性\方法,修改属性值\方法
- 遍历一个类的所有成员变量\属性\所有方法
runtime的相关应用
1.NSCoding(归档和解归档,利用 runtime 遍历对象的所有属性)
2.字典->转模型(利用 runtime遍历模型对象的所有属性,根据属性名从字典中取出对应的值,设置到模型的属性上)
3.KVO(利用 runtime 动态产生一个类)
4.用于封装框架(想怎么改就怎么改)
需要引入头文件
头文件* <objc/runtime.h>* <objc/message.h>
常用的先关函数
objc_msgSend:给对象发送消息
class_copyMethodList:遍历某个类所有的方法
class_copyIvarList:遍历某个类所有的成员变量
class_getClassMethod:获得某个类方法
ivar_getName:查看成员变量
Ivar:成员变量
Method:成员方法
- 相关的定义
相关定义:
/// 描述类中的一个方法
typedef struct objc_method *Method;
/// 实例变量
typedef struct objc_ivar *Ivar;
/// 类别Category
typedef struct objc_category *Category;
/// 类中声明的属性
typedef struct objc_property *objc_property_t;
类在 runtime 中的表示:
//类在runtime中的表示
struct objc_class {
Class isa;//指针,顾名思义,表示是一个什么,
//实例的isa指向类对象,类对象的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;
/* Use `Class` instead of `struct objc_class *` */
代码示例:
+ (void)property
{
unsigned int outCount;
// 获取属性列表
objc_property_t *propertyList = class_copyPropertyList(self, &outCount);
for (unsigned int i = 0; i<outCount; i++) {
NSLog(@"属性=======%@",@(property_getName(propertyList[i])));
}
// 获得方法列表
Method * methodList = class_copyMethodList(self, &outCount);
for (unsigned int i = 0; i< outCount; i++) {
NSLog(@"方法=====%@",NSStringFromSelector(method_getName(methodList[i])));
}
// 获得成员变量
Ivar * ivarList = class_copyIvarList(self, &outCount);
for (unsigned int i = 0; i<outCount; i++) {
NSLog(@"成员变量:%@",@(ivar_getName(ivarList[i])));
}
// 获得协议列表
__unsafe_unretained Protocol ** protocolList = class_copyProtocolList(self, &outCount);
for (unsigned int i = 0 ; i < outCount; i++) {
NSLog(@"协议:%@",@(protocol_getName((protocolList[i]))));
}
}