iOS探索底层-类的结构探索(上)

前言

在上篇文章iOS底层探索——对象的本质&isa分析中,我们知道了对象里面含有一个叫做isa的指针,并且通过isa指针,从对象找到了他所属的类,今天我们就来探索一下关于类的秘密。

类的isa

元类

我们知道,对象的isa指向的是类,那么类里面是不是也会有同样的东西的,他指向的又是什么呢?带着问题,我们开始我们的探索

image.png
我们使用对象的探索思维,同样打印出DMPerson类的内容,对第一个八位我们猜想他是不是类似isa的结构呢,使用掩码进行运算

image.png
我们发现计算出来的地址0x0000000100008200打印出来是DMPerson。我们再打印DMPerson类的地址0x0000000100008228,这两个地址并不一样,但是都打印出了DMPerson,那么类是不是也跟对象一样,每个对象都有不同的地址呢?

void dmTestClassNum(void){
    Class class1 = [DMPerson class];
    Class class2 = [DMPerson alloc].class;
    Class class3 = object_getClass([DMPerson alloc]);
    Class class4 = [DMPerson alloc].class;
    NSLog(@"\nclass1:%p\nclass2:%p\nclass3:%p\nclass4:%p",class1,class2,class3,class4);
}
复制代码

我们通过不同的方式,多创建几个类,并且打印出他的地址,其结果如下

image.png
我们发现所有的类打印输出的结果都是0x0000000100008228这个地址,说明同一个类,在内存中只有一个地址。那么0x0000000100008200这个地址所代表的的又是什么呢?下面我们通过辅助软件MachOView来看看我们符号表里面的内容。

image.png
由于我们的工程只有DMPerson这一个类,所以在__DATA__objc_classrefs这个结构下,只有一行。继续探索

image.png
在全部的符号表中,搜索class这个关键字,我们神奇的发现,除了_OBJC_CLASS_$_DMPerson以外,还有一个叫做_OBJC_METACLASS_$_DMPerson的东西,这就是我们要找的0x0000000100008200中存的内容,我们称之为元类元类并不是我们主动生成的,是系统在编译期自动生成的,所以我们可以得出下面一个结论

image.png
对象的isa指向类,而类的isa指向元类,类可以看做是元类的一个对象,我们称之为类对象

根元类

在上面的探索中,我们引出了一个新的概念元类类对象isa指向的就是元类,那么元类有没有isa呢?如果有,他的isa指向的又是什么呢?

image.png
按照的探索顺序,我们对元类进行同样的操作,发现元类也存在isa,他指向的是NSObject,而这个地址与NSObject类的地址同样不同。我们再来打印看看NSObject的元类是什么呢?

image.png
我们发现NSObjectisa指向与DMPerson的元类的isa指向一样。由于NSObject是OC中所有类的根类,所以我们又把NSObject的元类,称之为根源类
那么上面的图,就进化为了这样:

image.png

isa的走位图

我们继续猜想,既然对象元类都有isa,那么根元类有没有isa呢?他指向什么呢?

image.png
我们用同样的流程对根源类进行了探索,发现根源类isa指向了他自己,所以整个isa的查找流程就形成了闭环,我们继续将上面的图进行升级,得到了最终的

image.png

类的superclass

在之前的探索中,我们知道,类在底层中实际上是objc_class这个结构,那么我们就来看看这个结构的组成

struct objc_class : objc_object {
  objc_class(const objc_class&) = delete;
  objc_class(objc_class&&) = delete;
  void operator=(const objc_class&) = delete;
  void operator=(objc_class&&) = delete;
    // 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

    ……其他的方法……
 }
复制代码

这里省略的部分方法,我们暂时先不研究,我们发现在这个结构里面有几个东西

  • Class isa:指向元类的指针
  • Class superclass:指向父类的指针
  • cache_t cache:缓存
  • class_data_bits_t bits:类存储信息的地方

isa指针在上面我们已经进行过探索了,我们接下来探索一下superclass指针
我们在之前的代码中添加了一个叫做DMWorker的类,继承自DMPerson

@interface DMWorker : DMPerson

- (void)saygood;

@end

@implementation DMWorker

- (void)saygood
{
    NSLog(@"good");
}

@end
复制代码

现在我们来看看他的继承关系

image.png
以图来实例的话

image.png
从上面的探索中我们知道,类的isa指向元类,那么元类是不是也有这样的继承关系呢?我们继续往下探索

image.png
从图中的探索我们可以看得,元类也同样存在跟类一样的继承关系,最后到NSObject元类的父类则指向了NSObject本身,那么我们上面的那张图就可能更新为

image.png

总结

上面的isa的图和继承的图,苹果有一张经典的图来表示他们

image.png
相信大家应该都看过这个图,经过我们之前的分析,对这张图的理解,应该已经更加深刻了。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享