在上篇文章中,我们通过方法调用,间接证明了isa指针与superClass指针的指向,这篇文章我们通过isa的实现来证明其指向。
继续看图:
为了从指针层面更加清晰的看isa指针和superClass指针的指向,我们模仿Class结构体,定义如下结构体变量:
在结构体 PM_ojbc_class中包含isa和superClass两个结构体指针变量。
接着我们创建三个实例对象:分别是NSObject实例对象object,Person类实例变量person,Student类实例变量student;
再分别创建三个类的类对象:
最后创建三个元类对象:
对象创建完成以后,我们首先来证明isa指针的指向,
即实例对象的isa指针指向类对象,类对象的isa指针指向元类对象,元类对象的isa指针指向元类的基类。
运行程序,在控制台依次输入以下调试命令:
在lldb调试器中,p/x的意思是以16进制打印对象的地址。
在这个截图中,我们首先打印person类对象地址,即1318结尾的地址。
然后打印实例对象person的isa指针指向的地址:即1319结尾。
注意isa指针需要与魔数0x00007ffffffffff8ULL进行与操作,得到isa最终指向的地址。
至于为什么要与这个数进行与操作,牵涉到runtime中位域的问题,后面我们会仔细剖析,在这里我们先记住要进行这个操作就好。
取余后,得到1318结尾的地址,即我们最初打印的类对象地址,至此我们证明了实例对象的isa指针指向类对象。
然后同样的操作,我们通过类对象的isa指针与0x00007ffffffffff8ULL进行与操作,得到12f0结尾的地址,与元类地址进行比较,正好相等。
这一步我们其实证明了上图中的这个流程:
二、然后我们来看superClass指针的指向,在控制台进行如下操作:
通过superClass指针不需要进行与操作,就可以直接得到父类对象。
1.由于Person类继承自NSObject,person元类对象的superClass指针即指向NSObject的元类对象,即0x00007fff9c5bf0f0。
2.再继续查找NSObject元类的superClass指针的指向:0x00007fff9c5bf140,也就是NSObject的类对象。
3.查看NSObject类对象的superClass,指向为空。
这三步操作对应图中的指向:
通过以上拆解,相信对isa和superClass的指针指向问题已经清楚了,可以自行验证student类和NSObject类的指针指向。