由于 Objc2.0 的改版, 很多旧的描述已经过时, 一下是对 Objc2.0 的总结
Class
Class 在 Runtime 中是对象的模型
其在 Runtime 中的定义为是一个 objc_class 结构体
typedef struct objc_class *Class;
而 objc_class 的定义如下,
struct objc_class : objc_object {
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
......
}
因为 objc_class 继承与 objc_object 所以每个 Class 都有一个 isa 指针,而 isa 的类型是 isa_t 类型。
isa 指针
isa 表示这个对象是哪个类,
isa 的数据结构是 isa_t, 而 isa_t 的结构描述是
union isa_t
{
isa_t() { }
isa_t(uintptr_t value) : bits(value) { }
Class cls;
uintptr_t bits;
......
};
可以看出, 每个 isa 中都有一个 Class 类型的 cls 和 bits 字段。 而 cls 字段表示 isa 指向的 class
类、父类、元类
在网上众多文章中,都没具体提到 Class 为什么是对象,以及没说清到底 Class 是到底是类的描述还是实例对象。下面我们一起来了解一下到底什么是类。
在 Runtime 中,类(Class)的概念和其他面向对象语言有点不同,这里的 Class 并不是一个对象的描述,而是在 Class 加载的时候,Runtime 生成的一块存在初始化好的 objc_class 结构体实例来表示一个 Class 在 Runtime 的描述, 这也解释了为什么 Class 本身也是一个对象,每个 class 都是独一无二的。
父类:顾名思义就是一个类的所继承的类。在 objc_class 中 superclass 定义。
元类:我们知道 isa 指针指向一个当前对象的类,而这个类也是对象,那么它的 isa 指向什么呢?这就是元类。元类的作用主要是用来存储查找类方法。
下面我们通过具体实例来解释下对象在内存中如何表示:
如:自定义一个 XXObject 类,
- Runtime 在加载 XXObject 的时候会初始化一个包含 XXObject 的 class 对象用来表示 XXObject 类,我们给它取个名字叫 rt_XXObject.
- 因为 rt_XXObject 也是一个对象(Class 本身也还是一个对象),所以它的 isa 也要指向一个对象,所以 Runtime 会生成类似步骤1中的内存对象,但是这个对象只存放类方法,这个类就是元类,并且将 rt_XXObject 的 isa 指向它,但是元类也是一个对象那它的 isa 指向哪儿,总不可能无限下去,于是 Apple 让元类的 isa 指向 rootMetaClass(根元类),这里是 NSObject 的 元类,而根元类的元类指向 nil 来形成一个闭环。
- 当我们创建对象,调用
[[XXObject alloc]init]
时,runtime 生成一个 class 对象,并将 isa 指针指向 rt_XXObject,表示这个对象是 XXObject 的实例。
下面有张图可以加深理解
objc-isa-class-diagra
网友评论