在OC的类结构中,存在这样的结构:
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();
}
...
...
}
类结构中包含了class_data_bits_t结构,这个结构实际上上是由一个指针(class_rw_t *)和一些关于类初始化状态的的标识组成.可以通过
#if !__LP64__
...
// data pointer
#define FAST_DATA_MASK 0xfffffffcUL
...
#elif 1
...
#define FAST_DATA_MASK 0x00007ffffffffff8UL
...
#else
...
#define FAST_DATA_MASK 0x00007ffffffffff8UL
...
#endif
class_rw_t* data() {
return (class_rw_t *)(bits & FAST_DATA_MASK);
//FAST_DATA_MASK的定义跟ISA_MASK很相近
}
来获取类结构中的class_rw_t指针.而class_rw_t结构中又包含了一个const class_ro_t *类型的指针实现,那么class_rw_t和class_ro_t这两个看起来只有一个字符差距的结构有什么不一样呢?
成员变量的不同
包含基本成员变量的不同
struct class_ro_t {
uint32_t flags; // class_rw_t也有
uint32_t instanceStart; //class_rw_t没有
uint32_t instanceSize;//class_rw_t没有
#ifdef __LP64__
uint32_t reserved;
#endif
const uint8_t * ivarLayout;
const char * name;
method_list_t * baseMethodList;//与class_rw_t中的methods对应
protocol_list_t * baseProtocols;//与class_rw_t中的protocols对应
const ivar_list_t * ivars; //class_rw_t没有
const uint8_t * weakIvarLayout;//class_rw_t没有
property_list_t *baseProperties; //与class_rw_t中的properties对应
/*
class_rw_t多出了以下成员变量
Class firstSubclass;
Class nextSiblingClass;
char *demangledName;
*/
...
...
}
对比发现,class_ro_t结构中与class_rw_t对应的的主要成员变量都使用了base做区分,说明class_ro_t的结构更加贴近类本身的结构,class_rw_t像是类拓展出来的.
可变性不同
struct class_rw_t {
...
const class_ro_t *ro;
...
}
在关于类的实现中,几乎所有引用到class_ro_t变量的地方都是使用了const关键字做修饰,更像是一个静态不愿意被外界修改的属性;而引用到class_rw_t变量就没有这样的限制.
作用不同
使用objc源码进行调试,在main中创建对象
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSObject *obj = [[NSObject alloc] init];
}
}
并在setData处进行断点:
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); //在此处下断点
}
...
...
}
然后会发现如下调用:
发现在_read_images之后就调用了realizeClassWithoutSwift函数:
ro = (const class_ro_t *)cls->data();
if (ro->flags & RO_FUTURE) {
// This was a future class. rw data is already allocated.
rw = cls->data();
ro = cls->data()->ro;
cls->changeInfo(RW_REALIZED|RW_REALIZING, RW_FUTURE);
} else {
// Normal class. Allocate writeable class data.
rw = (class_rw_t *)calloc(sizeof(class_rw_t), 1);
rw->ro = ro;
rw->flags = RW_REALIZED|RW_REALIZING;
cls->setData(rw);
}
而此时ro已经是一个实例化之后的class_ro_t *指针,所以class_ro_t *是在类编译时就已经完成初始化赋值且不可被改变的.而class_rw_t结构则是可以通过方法进行修改.例如:
static SEL *
addMethods(Class cls, const SEL *names, const IMP *imps, const char **types,
uint32_t count, bool replace, uint32_t *outFailedCount)
{
runtimeLock.assertLocked();
assert(names);
assert(imps);
assert(types);
assert(cls->isRealized());
...
...
if (newlist->count > 0) {
// fixme resize newlist because it may have been over-allocated above.
// Note that realloc() alone doesn't work due to ptrauth.
method_t::SortBySELAddress sorter;
std::stable_sort(newlist->begin(), newlist->end(), sorter);
prepareMethodLists(cls, &newlist, 1, NO, NO);
cls->data()->methods.attachLists(&newlist, 1);
flushCaches(cls);
} else {
// Attaching the method list to the class consumes it. If we don't
// do that, we have to free the memory ourselves.
free(newlist);
}
if (outFailedCount) *outFailedCount = failedCount;
return failedNames;
}
所以可以理解为class_ro_t存储的是类在编译期就已经确定的特性,而class_rw_t则是提供在运行时进行类延展的能力.
需要注意的是,通过运行时使用
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) {
_object_set_associative_reference(object, (void *)key, value, policy);
}
来为对象添加属性并不是通过class_rw_t来实现的,而是通过全局维护的hashMap来实现的.