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 存放的是类方法列表。
方法 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 指向图: