文章目录
- OC对象的本质
- [实例对象, 类对象, 元类的关系](#实例对象, 类对象, 元类的关系)
OC对象的本质
oc的对象, 类, 主要是基于结构体去实现的
所有的OC对象都继承自NSObject, 类主要是基于结构体去实现的
objc
// 类的结构体
struct NSObject_IMPL {
Class isa; // Class是一个结构体类型, isa是一个结构体指针
}
继承自NSObject 的对象结构大致是, 这是一个继承自NSobject 的对象的Student, (被添加了name 和 age 两个属性)
objc
struct Struct_IMPL {
struct NSObject_IMPL NSobject_IVARS; (Class class)
int _age;
NSString* _name;
}
OC的实例对象, 类对象. 元类对象
OC主要包括了3种对象
- 实例对象
- 类对象
- 元类对象
类对象
实例对象就是通过类 alloc 出来的对象 , 每一次调用 alloc 都会产生一个新的instance对象
- isa指针
- 其他成员变量
类对象
通过实例对象的class方法或类的class方法获取到类对象, 每个类在内存中有且只有一个class 对象
- isa指针
- superclass指针
- 类的属性信息 (@property)
- 类的对象方法信息
- 类的协议信息
- 类的成员变量信息
元类对象
每个类在内存中有且只有一个 元类对象 (meta-class)
- isa指针
- superclass指针
- 类的方法信息
实例对象, 类对象, 元类的关系
在 Objective-C 中,一切皆对象:
- 普通类对象 :比如
[NSObject class]获取的是NSObject的类对象,用于创建实例([[NSObject alloc] init])。 - 元类 (Meta Class) :是类对象的 "类",专门存储类方法(
+开头的方法)的地方。每个类都有且仅有一个元类,类对象的isa指针指向元类。
objc_getMetaClass 的核心作用就是获取指定类的元类对象
isa指针概念
每个 OC 对象的第一个成员变量 就是 isa 指针,它指向该对象所属的类,是 OC 消息发送机制的核心。
isa的三条链
第一条: 实例->类对象
objc
Dog *dog1 = [[Dog alloc] init];
Dog *dog2 = [[Dog alloc] init];
// 两个实例的 isa 都指向同一个 Dog 类对象
dog1->isa == dog2->isa == [Dog class] // YES
在 Objective-C 中:
- 类对象(如
Dog类对象)是单例的,程序运行期间只会存在一个。- 每次通过
[[Dog alloc] init]创建实例时,新实例的isa成员都会指向这个唯一的Dog类对象,所以dog1->isa和dog2->isa会指向同一个地址,与[Dog class]的结果也完全相等。
同一个类的所有实例对象的isa指针,都会指向这个类唯一的类对象
第二条 类对象 -> 元类
objc
// Dog类对象的 isa 指向 Dog 元类
[Dog class]->isa == objc_getMetaClass("Dog") // YES
```
```
Dog类对象 ──isa──► Dog元类
第三条 元类 -> 根元类 -> 自己
objc
// 所有元类的 isa 最终指向 NSObject 元类
// NSObject 元类的 isa 指向自己,形成闭环
Dog元类 ──isa──► NSObject元类 ──isa──► NSObject元类(自己)
isa 完整链路图
isa isa isa(自己)
Dog实例 ────────────► Dog类对象 ────────► Dog元类 ──────────► NSObject元类
│ │ │ ▲
superclass │ superclass │ superclass │ │
▼ ▼ ▼ │isa
NSObject实例 ──────────► NSObject类对象 ───► NSObject元类 ───────────┘
isa isa
这里可以用一张图进行总结

获取元类的方法
objc
// 方式一:通过类对象获取元类
Class metaClass = object_getClass([Dog class]);
// 方式二:通过类名字符串获取元类
Class metaClass = objc_getMetaClass("Dog");
// 判断一个 Class 是否是元类
BOOL isMeta = class_isMetaClass(metaClass); // YES
获取元类必须用
object_getClass()或objc_getMetaClass(),不能用[Dog class],因为[Dog class]永远返回类对象而不是元类。