class_ro_t和class_rw_t的区别 iOS
class_ro_t
class_ro_t
存储了当前类在编译期就已经确定的属性
、方法
以及遵循的协议
,里面是没有分类的方法的。那些运行时添加的方法将会存储在运行时生成的class_rw_t
中。
ro
即表示read only
,是无法进行修改的。
struct class_ro_t { uint32_t flags; uint32_t instanceStart; uint32_t instanceSize; #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 *baseProperties; method_list_t *baseMethods() const { return baseMethodList; } }
class_rw_t
ObjC
类中的属性、方法还有遵循的协议等信息都保存在 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; // 指向只读的结构体,存放类初始信息 /* 这三个都是二维数组,是可读可写的,包含了类的初始内容、分类的内容。 methods中,存储 method_list_t ----> method_t 二维数组,method_list_t --> method_t 这三个二位数组中的数据有一部分是从class_ro_t中合并过来的。 */ method_array_t methods; // 方法列表(类对象存放对象方法,元类对象存放类方法) property_array_t properties; // 属性列表 protocol_array_t protocols; //协议列表 Class firstSubclass; Class nextSiblingClass; //... }
class_rw_t生成时机
class_rw_t
生成在运行时,在编译期间,class_ro_t
结构体就已经确定,objc_class
中的bits
的data部分存放着该结构体的地址。在runtime
运行之后,具体说来是在运行runtime的
realizeClass方法时,会生成
class_rw_t结构体,该结构体包含了
class_ro_t,并且更新data部分,换成
class_rw_t`结构体的地址。
类的realizeClass
运行之前:
类的
realizeClass
运行之后:
细看两个结构体的成员变量会发现很多相同的地方,他们都存放着当前类的属性、实例变量、方法、协议等等。区别在于:class_ro_t
存放的是编译期间就确定的;而class_rw_t
是在runtime时才确定,它会先将class_ro_t
的内容拷贝过去,然后再将当前类的分类的这些属性、方法等拷贝到其中。所以可以说class_rw_t
是class_ro_t
的超集,当然实际访问类的方法、属性等也都是访问的class_rw_t
中的内容
转自: https://www.jianshu.com/p/823eaedb3697