返回

OC底层研究3--isa的初始化和指向分析

IOS


开始继续学习研究OC源码,这次研究的是isa的初始化和指向分析。

1. 概念

isa : 一个指向该对象的类的指针。 可以看出,Class 是一个objc_class 类型的结构体。 而id类型,则是objc_object 类型的结构体.

2. isa 的初始化

在这里,初始化isa并不困难,简而言之就是对象isa结构体中的两个成员变量指针,isa和superclass,分别指向本类的Class结构体和父类的Class结构体。

当OC编译器编译该段代码后,会编译成这样:

class_getName((Class)isa)) == "Dog"

3. isa 的指向分析

说起来很轻松,对于那些不会动态创建类和不会派生子类的应用,是没有任何问题的,其指向始终是固定的。但这只是冰山一角,isa的指向最终取决于在程序中如何创建对象。

如果对象是通过objc_alloc方式创建,那么isa的值是Class结构体的地址,是唯一确定的。

如果对象是通过动态创建的子类创建,那么isa的值是这个动态子类的Class结构体的地址。

我们可以通过:class_getInstanceSize((Class)isa),来判断isa到底指向的是父类的Class结构体还是子类的Class结构体。 当isa指向父类Class结构体时,其父类的Class结构体里方法表指向父类的实例方法,其子类的Class结构体里方法表指向子类的实例方法。 当isa指向子类的Class结构体时,其子类的Class结构体里方法表指向子类的实例方法,其父类的Class结构体里方法表指向父类的实例方法。 这样看起来很是令人费解,不如直观的看一下:

从图中可以看出,子类的isa指向子类的Class结构体,其子类的Class结构体里方法表指向子类的实例方法,其父类的Class结构体里方法表指向父类的实例方法。

由上我们得出,isa 指向的是某个对象的类,如果这个类是动态创建的子类,那么isa指向的类是不确定的,可能指向父类,也可能指向子类,那么唯一确定的就只有对象的类名了。我们可以通过class_getName((Class)isa))来获取对象的类名。

在理解了isa的初始化和指向分析之后,再来探讨isa和类的关联就不再是问题了,同时,也对理解Runtime和消息发送机制非常有帮助。