Runtime
Runtime简介
首先,高级语言要转换为机器语言才可以在机器上运行,高级语言需要经过预处理后先编译为汇编语言,在汇编为机器语言,OC需要转换为C语言才可以编译为汇编语言,而OC到C的转换有runtime来实现的。它动态的创建类、对象,用于支持将代码在编译和链接时需要的做的内容推迟到运行时去决策,也就是在运行时使用消息转发来实现函数调用,使OC语言具有动态性,
runtime的使用
通过Object-C源代码进行交互
我们使用OC编写的代码,都会转化为runtime来实现,OC中的类、对象、协议都会转换为runtime的数据结构
通过NSObject类中定义的方法交互
NSObject是大部分类的父类,其本身就具有了一些非常具有运行时动态特性的方法,比如respondsToSelector:方法可以检查在代码运行阶段当前对象是否能响应指定的消息,所以使用这些方法也算是一种与Runtme的交互方式
-class方法返回对象的类;
-isKindOfClass: 和 -isMemberOfClass: 方法检查对象是否存在于指定的类的继承体系中(是否是其子类或者父类或者当前类的成员变量);
-respondsToSelector: 检查对象能否响应指定的消息;
-conformsToProtocol:检查对象是否实现了指定协议类的方法;
-methodForSelector: 返回指定方法实现的地址。
在开始我们就介绍了runtime是OC语言具有动态性,就是在编译的时候动态的创建对象、类,下面我们看看runtime的基本数据结构
通过直接调用运行时函数
直接使用runtime的API完成某种需求或功能
runtime的基本数据结构
1、类对象
typedef struct objc_class *Class
类对象是指向objc_class的指针,其中objc_class结构如下,从下面可以看出objc_class继承objc_object,类也是一个对象
struct objc_class : objc_object {
//objc_class的指针,指向父类结构体
Class superclass;
cache_t cache; // formerly cache pointer and vtable
//bits用来存储类的属性、方法、协议等信息,class_data_bits_t是被Mask的结构体。根据不同的Mask,取出不同的值
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
//获取bits中的信息--1
class_rw_t *data() {
return bits.data();
}
void setData(class_rw_t *newData) {
bits.setData(newData);
}
.......
bool hasCxxCtor() {
// addSubclass() propagates this flag from the superclass.
assert(isRealized());
return bits.hasCxxCtor();
}
void setHasCxxCtor() {
bits.setHasCxxCtor();
}
bool hasCxxDtor() {
// addSubclass() propagates this flag from the superclass.
assert(isRealized());
return bits.hasCxxDtor();
}
void setHasCxxDtor() {
bits.setHasCxxDtor();
}
}
1)class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
,在 objc_class
结构体中的注释写到 class_data_bits_t
相当于 class_rw_t
指针加上 rr/alloc 的标志。通过对bits进行FAST_DATA_MASK,获取bits中信息,返回值是class_rw_t结构体,下面是获取class_rw_t*指针的便捷方法
class_rw_t* data()
{
//将 bits 与 FAST_DATA_MASK 进行位运算,取其中的 [3, 47] 位转换成 class_rw_t * 返回
return (class_rw_t *)(bits & FAST_DATA_MASK);
}
其中class_rw_t结构如下
struct class_rw_t {
uint32_t flags;
uint32_t version;
const class_ro_t *ro;
method_array_t methods;
property_array_t properties;
protocol_array_t protocols;
Class firstSubclass;
Class nextSiblingClass;
};
在上面的结构中存在一个ro指针,结构类型位class_ro_t,该结构存储了编译期确定的属性、方法和协议;class_ro_t的结构如下。
struct class_ro_t {
uint32_t flags;
uint32_t instanceStart;
uint32_t instanceSize;
uint32_t reserved;
const uint8_t * ivarLayo