iOS 升級打怪 - NSObject 的底層資料結構

語言: CN / TW / HK

Objective-C 的物件型別

本文objc4 的原始碼版本為:objc4-818.2.下載地址

在 Objective-C 中物件共有三種類型,分別是例項物件、類物件和元類物件。 * 例項物件 NSObject *obj = [NSObject new];

例項物件記憶體中包含 isa:指向類物件指標、成員變數:剩餘成員變數的值。 * 類物件 Class classObj = [obj class];

類物件底層實現為 struct objc_class,下面是精簡之後的原始碼(完整原始碼請參見在objc-runtime-new.h 檔案):

``` /// Represents an instance of a class. struct objc_object { Class _Nonnull isa OBJC_ISA_AVAILABILITY; };

struct class_rw_t { const method_array_t methods() const { ... } const property_array_t properties() const { ... } const protocol_array_t protocols() const { ... } };

struct objc_class : objc_object { // Class ISA; Class superclass; class_rw_t *data() const { return bits.data(); } } ``` isa:指向元類的指標;superclass:指向父類的指標;methods:例項方法列表;properties:屬性列表;protocols:協議列表。

  • 元類物件 Class metaClassObj = object_getClass(classObj); 元類物件與類物件底層結構相同,只不過儲存的內容不同。元類物件的 isa 存放的是指向基類元類物件的指標;methods 存放的是類方法列表。

memory-layout.png

方法 class 與 object_getClass 的區別

  • class 方法:例項方法底層呼叫的 object_getClass ,用來獲取例項物件的類物件(Swift 請用 type(of: anObject) 代替);類方法則直接返回本身。 ```
  • (Class)class { return self; }

  • (Class)class { return object_getClass(self); } ```

所以這種方式並不能獲取元類物件:[[obj class] class];

  • object_getClass:獲取 obj 的 isa 指向的物件。即傳入例項物件,返回類物件;傳入類物件,返回元類物件。 Class object_getClass(id obj) { if (obj) return obj->getIsa(); else return Nil; }

isa 與 superclass

isa

isa 的作用是用來得到類物件或者元類物件的地址,從而去呼叫方法等。若是例項物件的 isa, isa & ISA_MASK 即可得到類物件的地址;若是類物件的 isa,isa & ISA_MASK 即可得到元類物件的地址。

以前 isa 直接存放的就是類物件或者元類物件的地址,arm64 架構開始需要 isa & ISA_MASK 才能獲取地址。

  • isa 指向:
    • 子類例項物件的 isa 指向子類類物件;子類類物件的 isa 指向 子類元類物件;子類元類物件的 isa 指向 根類元類物件。
    • 父類例項物件的 isa 指向父類類物件;父類類物件的 isa 指向 父類元類物件;父類元類物件的 isa 指向 根類元類物件。
    • 根類例項物件的 isa 指向根類類物件;根類類物件的 isa 指向 根類元類物件;根類元類物件的 isa 指向自己。

superclass

superclass 的作用是找到父類物件,它存放的值即為父類類物件的地址。

  • superclass 指向:
    • 子類類物件的 superclass 指向 父類類物件;父類類物件的 superclass 指向 根類類物件;根類類物件的 superclass 指向 nil。
    • 子類元類物件的 superclass 指向 父類元類物件;父類元類物件的 superclass 指向 根類元類物件;根類元類物件的 superclass 指向根類類物件。

isa 與 superclass 指向圖:

isa-superclass.png