「クラス」の根底にある原則に関するSwiftの詳細な分析

Objective-Cクラス

ここに画像の説明を挿入

  • OCに精通している人は、上の図に精通している必要があります。はい、これはAppleの公式インスタンスオブジェクト、クラス、およびメタクラスの関係図です。isa、スーパークラス、およびメタクラスの関係を鮮明に示しています。継承関係
  • OCクラスの実装原理を見れば、OCクラスはobjc_classから継承され、NSObjectはOCのタイプであり、objc_objectはcのタイプであることがわかります。
  • 構造タイプobjc_classはobjc_objectタイプを継承します。ここで、objc_objectも構造であり、isa属性を持っているため、objc_classもisa属性を持っています。
  • NSObjectのisaは、下部のClassによって定義され、クラスの下部のコードはobjc_class型から取得されるため、NSObjectにもisa属性があります。
  • NSObjectはクラスです。これを使用してインスタンスオブジェクトobjcを初期化します。objcはobjc_objectの特性を満たします(つまり、isa属性を持ちます)。これは主に、isaがNSObjectによってobjc_classから継承され、objc_classがobjc_objectから継承され、objc_objectがisaを持っているためです。属性。したがって、オブジェクトにはisaがあります。これは、現在のobjc_objectを指していることを意味します。
  • objc_objectは現在のルートオブジェクトであり、すべてのオブジェクトにはそのような特性objc_objectがあります。つまり、isa属性があります。
  • OCクラスの分析と調査については、以前のブログを参照してくださいクラスクラスの基本原則に関するiOSの詳細な分析
  • では、Swiftのクラスも同じですか?Swiftのクラスの構造は何ですか?その基礎となる実装はどうですか?
クラス構造
1.構造
  • 前回のブログでは、Swiftのインスタンスオブジェクトを分析しました。インスタンスオブジェクトの場合、その本質は、デフォルトのメモリサイズが16バイトのHeapObject構造です(メタデータ8バイト+ refCounts 8バイトの2つの属性があります)。
  • Swiftオブジェクト分析については、私のブログを参照してくださいオブジェクトの基本原理に関するSwiftの詳細な分析
  • HeapObjectのメモリ割り当てを理解すると、メタデータに気付くはずです。そのタイプはHeapMetadataです。その特定のメモリ構造を見てみましょう。
2、HeapMetadataタイプ分析
  • TargetHeapMetaDataタイプのエイリアスであるHeapMetadata定義を入力し、パラメーターInprocessを受け取ります。
	struct InProcess;
	
	template <typename Target> struct TargetHeapMetadata;
	using HeapMetadata = TargetHeapMetadata<InProcess>;
	#else
	typedef struct HeapMetadata HeapMetadata;
	typedef struct HeapObject HeapObject;
	#endif
  • TargetHeapMetaData定義を入力します。これは、基本的にテンプレートタイプであり、いくつかの必要なデータ構造を定義します。この構造には属性はなく、初期化メソッドのみが渡され、MetadataKindタイプのパラメーターが渡されます。kindは渡されたインプロセスです。
	template <typename Runtime>
	struct TargetHeapMetadata : TargetMetadata<Runtime> {
    
    
	  using HeaderType = TargetHeapMetadataHeader<Runtime>;
	
	  TargetHeapMetadata() = default;
	  constexpr TargetHeapMetadata(MetadataKind kind)
	    : TargetMetadata<Runtime>(kind) {
    
    }
	#if SWIFT_OBJC_INTEROP
	  constexpr TargetHeapMetadata(TargetAnyClassMetadata<Runtime> *isa)
	    : TargetMetadata<Runtime>(isa) {
    
    }
	#endif
	};
	using HeapMetadata = TargetHeapMetadata<InProcess>;
  • constexpr TargetHeapMetadata(MetadataKind kind)は初期化メソッドであり、種類のタイプは次のとおりです。
名前
クラス 0x0
構造体 0x200
列挙型 0x201
オプション 0x202
ForeignClass 0x203
不透明 0x300
タプル 0x301
関数 0x302
実存的 0x303
メタタイプ 0x304
ObjCClassWrapper 0x305
ExistentialMetatype 0x306
HeapLocalVariable 0x400
HeapGenericLocalVariable 0x500
ErrorObject 0x501
LastEnumerated 0x7FF
  • TargetMetaData定義を入力します。kind属性があり、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;
  • TargetHeapMetadataとTargetMetaDataの定義から、初期化メソッドのパラメーターの種類のタイプはMetadataKindであることがわかります。
    • MetadataKind定義を入力します。#include "MetadataKind.def"があり、クリックして入力します。これは、すべてのタイプのメタデータを記録します。
    • TargetMetaData構造体定義に戻り、メソッドgetClassObjectを見つけます。このメソッドで種類を一致させると、戻り値はTargetClassMetadataタイプになります。Classの場合は、これ(現在のポインター、つまりメタデータ)をClassMetadataに直接強制します。
	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;
	    }
	  }
  • したがって、TargetMetadataとTargetClassMetadataは基本的に同じです。これは、メモリ構造ではポインタを直接変換できるため、構造は実際にはTargetClassMetadataであると見なすことができるためです。
  • TargetAnyClassMetadataから継承されたTargetClassMetadata定義を入力すると、クラス構造の一部である次の属性があります。
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;
  ...
}
  • TargetHeapMetadataから継承されたTargetAnyClassMetadata定義を入力します。
template <typename Runtime>
struct TargetAnyClassMetadata : public TargetHeapMetadata<Runtime> {
    
    
    ...
    ConstTargetMetadataPointer<Runtime, swift::TargetClassMetadata> Superclass;
    TargetPointer<Runtime, void> CacheData[2];
    StoredSize Data;
    ...
}
総括する
1.Swiftクラスの構成
  • メタデータの種類がクラスの場合、次の継承チェーンがあります。
    ここに画像の説明を挿入
  • 現在のクラスによって返される実際の型はTargetClassMetadataであり、TargetMetaDataには属性の種類が1つだけあり、TargetAnyClassMetaDataにはkind、superclass、cacheData、dataの4つの属性があります。
  • メモリに格納されている現在のクラスの属性は、TargetClassMetadata属性+ TargetAnyClassMetaData属性+ TargetMetaData属性で構成されているため、結果のメタデータ構造は次のようになります。
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;
    ...
}
2.SwiftクラスとOCクラスの比較
  • OCのインスタンスオブジェクトは基本的に構造であり、基になるobjc_objectを介して作成され、クラスはobjc_classから継承されます。Swiftのインスタンスオブジェクトも本質的に構造であり、タイプはHeapObjectであり、OCよりもrefCountが1つ多くなります。 ;
  • OCのメソッドはobjc_class構​​造class_rw_tのmethodListに格納され、swiftのメソッドはメタデータに格納されます。
  • OCのARCはハッシュテーブルを維持します。SwiftのARCには、オブジェクト内にrefCountsプロパティがあります。

おすすめ

転載: blog.csdn.net/Forever_wj/article/details/112256567