iOS 升级打怪 - NSObject 的底层数据结构

1,405 阅读2分钟

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