swift 类的结构3

124 阅读2分钟

「这是我参与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来验证

image.png

  • po metadata->getKind(),得到其kind是Class
  • po metadata->getClassObject()、x/8g 0x0000000110efdc70,这个地址中存储的是元数据信息!

所以TargetMetadataTargetClassMetadata本质上是一样的,因为在内存结构中,可以直接进行指针的转换,所以可以说,我们认为的结构体,其实就是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;
    ...
}

三、分析思路整理

image.png

四、swif与OC 类的结构对比

  • 实例对象 & 类

    • OC中的实例对象本质是结构体,是通过底层的objc_object模板创建,类是继承自objc_class
    • Swift中的实例对象本质也是结构体,类型是HeapObject,比OC多了一个refCounts
  • 引用计数

    • OC中的ARC维护的是散列表
    • Swift中的ARC是对象内部有一个refCounts属性
  • 方法列表

    • OC中的方法存储在objc_class结构体class_rw_tmethodList
    • swift中的方法存储在 metadata 元数据中