前置文章: iOS底层之类的重要组成部分-isa结构体分析
前言
从上篇文章中我们得知对象的isa指针中的shiftcls存储的是类指针的值,那么这个值到底代表什么呢,接下来让我们探索一下。
一、isa指针探索
首先我们先用对象的isa指针 & ISA_MASK得到如下结果:

isa指针的shiftcls的值
WJPerson,那么这个WJPerson会不会是类的地址的,接下来我们打印下WJPerson的类地址再来验证一下
WJPerson类的地址
isa的指针的shiftcls的结果一模一样,而shiftcls存储的又是类指针的值,所以我们可以得出结论:对象的isa指针指向的是类对象。那么类对象的isa指针指向什么呢?我们再来实验一下

类对象的isa指针结果
WJPerson,但是这个WJPerson和第一次打印的WJPerson的指针不一样,怎么回事,难道OC会创建两个一模一样的类吗?我们来测试下
void testClassPoint(){
Class class1 = [WJPerson class];
Class class2 = [WJPerson alloc].class;
Class class3 = object_getClass([WJPerson alloc]);
Class class4 = [WJPerson alloc].class;
NSLog(@"\n%p \n%p \n%p \n%p", class1, class2, class3, class4);
}
打印结果
0x100002140
0x100002140
0x100002140
0x100002140
从上述结果可知,OC只会存在一个类。那么我们之前获取到的第二个WJPerson是什么呢?
有的同学可能会知道在OC中还有一个元类的概念,元类和类有些相似,我们知道类是使用存储对象信息的,那么元类就是存储类对象信息的类。说了这么多,空口无凭,我们再来验证下

验证元类地址
类对象的isa指针指向元类。接下来我们再看下
元类的isa指针指向什么。
元类的isa指向
NSObject,那么这个NSObject是到底是类还是元类,接下来我们打印下NSObject的类和元类的地址
NSObject类和元类的地址
alloc重新创建一个对象获得的地址也一样。从图中我们发现WJPerson的元类的isa指针指向的是NSObject的元类。我们一般把NSObject叫做根类,那么NSObject的元类就叫做根元类。所以我们可以得出结论:元类的isa指针指向的是根元类。我们在看下根元类的isa指向的是什么。

根元类的isa指向
根元类的isa指针指向的是本身,这样就形成了一个闭环。我们总结一下我们的验证结果
- 对象的isa指针指向的是类对象
- 类对象的isa指针指向元类
- 元类的isa指针指向的是根元类
- 根元类的isa指针指向的是本身

isa走位图