"클래스"의 기본 원리에 대한 Swift의 심층 분석

Objective-C 클래스

여기에 사진 설명 삽입

  • OC에 능숙한 사람은 위의 그림을 잘 알고 있어야합니다. 예, 이것은 Apple의 공식 인스턴스 객체, 클래스 및 메타 클래스 관계 다이어그램입니다. isa, superclass 및 metaclass 간의 관계를 생생하게 보여줍니다. 상속 관계
  • 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 바이트의 두 가지 속성).
  • Swift 객체 분석, 내 블로그를 참조하십시오 : 객체의 기본 원리에 대한 Swift의 심층 분석 ;
  • HeapObject의 메모리 할당을 이해 한 후에는 Metadata 유형을 확인해야합니다. 해당 유형은 HeapMetadata입니다. 특정 메모리 구조를 살펴 보겠습니다.
둘째, 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는 전달 된 Inprocess입니다.
	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 종류)는 초기화 메서드이며 종류의 종류는 다음과 같습니다.
이름
수업 0x0
구조 0x200
열거 형 0x201
선택 과목 0x202
ForeignClass 0x203
불투명체 0x300
튜플 0x301
함수 0x302
실존 0x303
메타 타입 0x304
ObjCClassWrapper 0x305
ExistentialMetatype 0x306
HeapLocalVariable 0x400
HeapGenericLocalVariable 0x500
ErrorObject 0x501
LastEnumerated 0x7FF
  • TargetMetaData 정의를 입력하고 종류 속성이 있으며 종류의 유형은 이전에 전달 된 Inprocess입니다. 이것으로부터 종류의 경우 그 유형은 부호없는 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 클래스 구성
  • 메타 데이터의 종류가 Class 인 경우 다음과 같은 상속 체인이 있습니다.
    여기에 사진 설명 삽입
  • 현재 클래스가 반환하는 실제 유형은 TargetClassMetadata이며 TargetMetaData에는 하나의 속성 종류 만 있고 TargetAnyClassMetaData에는 4 개의 속성, 즉 종류, 수퍼 클래스, cacheData 및 데이터가 있습니다.
  • 메모리에 저장된 현재 Class의 속성은 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에서 상속됩니다. ;
  • OC의 메서드는 objc_class 구조 class_rw_t의 methodList에 저장되고 swift의 메서드는 메타 데이터에 저장됩니다.
  • OC의 ARC는 해시 테이블을 유지하고 Swift의 ARC는 객체 내부에 refCounts 속성을 가지고 있습니다.

추천

출처blog.csdn.net/Forever_wj/article/details/112256567