「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」。
- 进入
TargetMetaData定义,有一个kind属性,kind的类型就是之前传入的Inprocess。从这里可以得出,对于kind,其类型就是unsigned long,主要用于区分是哪种类型的元数据
// TargetMetaData 定义
struct TargetMetaData{
using StoredPointer = typename Runtime: StoredPointer;
...
StoredPointer kind;
}
// Inprocess 定义
struct Inprocess{
...
using StoredPointer = uintptr_t;
...
}
//******** uintptr_t 定义 ********
typedef unsigned long uintptr_t;
- 可以看出初始化方法中参数
kind的类型是MetadataKind,
2.2 getClassObject
- 回到TargetMetaData结构体定义中,找方法getClassObject
const TargetClassMetadata<Runtime> *getClassObject() const;
//******** 具体实现 ********
template<> inline const ClassMetadata *
Metadata::getClassObject() const {
//匹配kind
switch (getKind()) {
//如果kind是class
case MetadataKind::Class: {
// Native Swift class metadata is also the class object.
//将当前指针强转为ClassMetadata类型
return static_cast<const ClassMetadata *>(this);
}
case MetadataKind::ObjCClassWrapper: {
// Objective-C class objects are referenced by their Swift metadata wrapper.
auto wrapper = static_cast<const ObjCClassWrapperMetadata *>(this);
return wrapper->Class;
}
// Other kinds of types don't have class objects.
default:
return nullptr;
}
}
- 在该方法中去匹配
kind返回值是TargetClassMetadata类型
通过lldb来验证
po metadata->getKind(),得到其kind是Classpo metadata->getClassObject()、x/8g 0x0000000110efdc70,这个地址中存储的是元数据信息!
所以TargetMetadata 和 TargetClassMetadata本质上是一样的,因为在内存结构中,可以直接进行指针的转换,所以可以说,我们认为的结构体,其实就是TargetClassMetadata
2.3 TargetClassMetadata
进入TargetClassMetadata定义,继承自TargetAnyClassMetadata,有以下这些属性,这也是类结构的部分
template <typename Runtime>
struct TargetClassMetadata : public TargetAnyClassMetadata<Runtime> {
...
//swift特有的标志
ClassFlags Flags;
//实力对象内存大小
uint32_t InstanceSize;
//实例对象内存对齐方式
uint16_t InstanceAlignMask;
//运行时保留字段
uint16_t Reserved;
//类的内存大小
uint32_t ClassSize;
//类的内存首地址
uint32_t ClassAddressPoint;
...
}
- 当前类返回的实际类型是 TargetClassMetadata,而TargetMetaData中只有一个属性kind,TargetAnyClassMetaData中有3个属性,分别是kind, superclass,cacheData
- 当前Class在内存中所存放的属性由 TargetClassMetadata属性 + TargetAnyClassMetaData属性 + TargetMetaData属性 构成,所以得出的metadata的数据结构体如下所示
struct swift_class_t: NSObject{
void *kind;//相当于OC中的isa,kind的实际类型是unsigned long
void *superClass;
void *cacheData;
void *data;
uint32_t flags; //4字节
uint32_t instanceAddressOffset;//4字节
uint32_t instanceSize;//4字节
uint16_t instanceAlignMask;//2字节
uint16_t reserved;//2字节
uint32_t classSize;//4字节
uint32_t classAddressOffset;//4字节
void *description;
...
}
三、分析思路整理
四、swif与OC 类的结构对比
-
实例对象 & 类
- OC中的实例对象本质是结构体,是通过底层的
objc_object模板创建,类是继承自objc_class - Swift中的实例对象本质也是结构体,类型是
HeapObject,比OC多了一个refCounts
- OC中的实例对象本质是结构体,是通过底层的
-
引用计数
- OC中的ARC维护的是
散列表 - Swift中的ARC是对象内部有一个
refCounts属性
- OC中的ARC维护的是
-
方法列表
- OC中的方法存储在
objc_class结构体class_rw_t的methodList中 - swift中的方法存储在
metadata元数据中
- OC中的方法存储在