iOS 类的底层探索(上)
分析类对象内存存在个数
首先,我们创建一个LGPerson类继承于NSObject 通过不同获取类对象的方法来进行验证
Class class1 = [LGPerson class];
Class class2 = [LGPerson alloc].class;
Class class3 = object_getClass([LGPerson alloc]);
NSLog(@"\n%p-\n%p-\n%p",class1,class2,class3);
打印结果:

我们发现 类对象有且只有一个。
isa 流程探索
我们继续用LGPerson这个类来继续如下操作

通过不断地打印isa,我们发现可以总结出:
p对象isa --> LGPerson 类对象
LGPerson 类对象的 isa --> LGPerson 元类对象
LGPerson 元类对象 isa --> NSObject 根元类
NSObject 根元类 isa --> 自己

继承链
我们再来创建一个LGTeacher类继承于LGPerson,通过class_getSuperclass来获取父类

我们可以看到 LGTeacher->LGPerson->NSObject->nil
元类链
Class teacherMetaClass = objc_getMetaClass("LGTeacher");
NSLog(@"teacher 的元类 %@ - %p",teacherMetaClass,teacherMetaClass);
Class personMetaClass = objc_getMetaClass("LGPerson");
NSLog(@"person 的元类 %@ - %p",personMetaClass,personMetaClass);
Class superTeacherMetaClass = class_getSuperclass(teacherMetaClass);
NSLog(@"teacher 的元类的父类 %@ - %p",superTeacherMetaClass,superTeacherMetaClass);
Class superPersonMetaClass = class_getSuperclass(personMetaClass);
NSLog(@"person 的元类的父类 %@ - %p",superPersonMetaClass,superPersonMetaClass);
Class nsobjectClass = object_getClass(NSObject.class);
NSLog(@"nsobjectClass:%@ - %p",nsobjectClass,nsobjectClass);
打印结果如下:

从打印结果我们可以发现 LGTeacher的元类->LGPerson的元类->NSObject->nil

总结
通过以上的探索可以总结出经典的isa走位图

类结构的分析
首先分析Class,打开objc源码发现
typedef struct objc_class *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
...
}
我们发现类的底层实际上是一个objc_class结构体
内存偏移
现在我们要探索一下bits存储的数据,isa (8个字节)superclass(8个字节),cache_t(16字节),也就是总共偏移32个字节。
获取bits里面的methodLists

获取bits里面的propertyList

通过lldb找到了bit地址
通过源码查看class_data_bits_t结构
struct class_data_bits_t {
...
class_rw_t* data() const {
return (class_rw_t *)(bits & FAST_DATA_MASK);
}
...
}
查看class_rw_t结构
struct class_rw_t {
...
const method_array_t methods() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->methods;
} else {
return method_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->baseMethods()};
}
}
const property_array_t properties() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->properties;
} else {
return property_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->baseProperties};
}
}
...
}
properties()、 methods()这两个方法可以获取属性
总结
1.类在底层实际上是一个结构体objc_class, objc_class实际上也是继承objc_object,所以类实际上也是对象
2.此次 我们只是对对象的方法和属性的存储进行了探究,可以看出对象的方法、属性实际上存在类的class_data_bits_t 的class_rw_t里面\
下一篇章将继续探索成员变量存储 类方法的存储
转载自:https://juejin.cn/post/7089052408852152327