Runtime系列文章
Runtime笔记(一)—— isa的深入体会(苹果对isa的优化)
Runtime笔记(二)—— Class结构的深入分析
Runtime笔记(三)—— OC Class的方法缓存cache_t
Runtime笔记(四)—— 刨根问底消息机制
Runtime笔记(五)—— super的本质
[Runtime笔记(六)—— Runtime的应用…待续]-()
[Runtime笔记(七)—— Runtime的API…待续]-()
Runtime笔记(八)—— 记一道变态的runtime面试题
我在OC对象的本质(下)—— 详解isa&superclass指针中,有介绍过Class对象的内存结构,如下图
本文就以此为起点,来仔细挖掘一下Class内部都有哪些宝贝。
(一)Class的结构简述
首先我们来看一下objc源码对Class的定义
struct objc_class : objc_object {
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable 方法缓存
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags 用于获取具体的类信息
class_rw_t *data() {
return bits.data();
}
void setData(class_rw_t *newData) {
bits.setData(newData);
}
//......下面的一堆方法/函数代码可以暂时不用关注
};
结构比较清晰
Class superclass;
——用于获取父类,也就是元类对象,它也是一个Class类型cache_t cache;
——是方法缓存class_data_bits_t bits;
——用于获取类的具体信息,看到bits
,想必看过我写的Runtime之isa的深入体会(苹果对isa的优化)这篇文章,一定会深有体会。- 紧接着有一个
class_rw_t *data()
函数,该函数的作用就是获取该类的可读写信息,通过class_data_bits_t
的bits.data()
方法获得,点进该方法看一下
class_rw_t* data() {
return (class_rw_t *)(bits & FAST_DATA_MASK);
}
可以看到,跟我们之前通过isa获取对象地址操作很像,这里是将类对象里面的class_data_bits_t bits;
和一个FAST_DATA_MASK
进行&
运算取得。返回的是一个指针,类型为class_rw_t *
,查看该类型的源码如下
struct class_rw_t {
// Be warned that Symbolication knows the layout of this structure.
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;
char *demangledName;
}
我们知道,OC类的方法、属性、协议都是可以动态添加,也就是可读可写的,从上面的源码中,可以发现确实是有对应的成员来保存方法、属性、协议的信息。而从该结构体的名字class_rw_t
,也暗含了上述的方法、属性、协议信息,是可读可写的。另外,我们知道Class类里面的成员变量是不可以动态添加的,也就是属于只读内容,相应的,可以推断const class_ro_t *ro;
就是指向了该部分内容信息的指针。同样,查看其源码
struct class_ro_t {
uint32_t flags;
uint32_t instanceStart;
uint32_t instanceSize;//instance对象占用的内存空间
#ifdef __LP64__
uint32_t reserved;
#endif
const uint8_t * ivarLayout;
const char * name;//类名
method_list_t * baseMethodList;//方法列表
protocol_list_t * baseProtocols;//协议列表
const ivar_list_t * ivars;//成员变量列表
const uint8_t * weakIvarLayout;
property_list_t *baseProper