iOS 类的底层原理分析(上)

2022-04-24  本文已影响0人  皮皮他爸

1、首先,我们先来看看类对象的内存地址

image.png

通过三种方式,分别获取类对象
第一种,通过类.class获取
第二种,通过实例对象.class获取
第三种,通过runtime获取

image.png

从接口很容易看出来,类对象只存在一份,因为内存地址一样

那接下来,我们来看看Class的本质是什么

image.png

其实Class就是一个objc_class的一个结构体指针

image.png

细心的同学可能已经看到了,objc_class继承了objc_object,说明了class也是对象,同样也有isa指针。

提到isa指针了,我们不得不了解的,对象的isa指针指向了类对象,那类对象的isa指针指向谁呢?

--------------> 元类,这个东西比较神秘,这个词并不陌生,但是你平时有使用过吗?
答案是肯定的,没有使用过,没有见过。

那我们为了证实这一个链路,看下lldb调试。
在调试之前,跟大家提一点,define ISA_MASK 0x007ffffffffffff8ULL,mask掩码,前八个字节实际是一个nonpointerisa,需要&mask掩码才可以得到正真的ISA地址

image.png

有同学可能不太了解上面的指令
x/6gx是打印出6个八字节内存,第一个八字节是isa地址,于上mask之后得到的是一个ClassObject,这个其实就是类对象
继续x/4gx打印出4个八字节内存,第一个八字节是isa地址,指向了元类(ClassObject)
有没有发现为什么实例对象的isa跟第一个八字节内存不一样,而类对象的isa跟第一个八字节一样内,因为实例对象的isa里面存了很多东西


image.png

从图片可以看出来有nonpointer,weak引用,还有引用计数等(苹果为了节省内存,通过位域的概念做了结构体优化)
那元类的isa指向谁呢?我们打印看一下


image.png
结果是一个NSObject,那这个NSObject跟我们平时使用的NSObject是同一个东西吗?

其实这个是根元类,并非我们平时使用的NSObject

学习了上面的内容,我们不难得到以下的总结:

instanceObj的isa -----> 类对象 isa----------->元类 isa---------->根元类 isa------> NSObject

现在相信大家对类、元类、根元类已经有了一定的了解了,下面我们看一下一段代码


image.png

我们可以得出一个结论:元类的父类=父类的元类,我们分析一下,ClassObject的父类是NSObject,ClassObject元类的父类class4=0x1046842c0,父类的元类就是class2=0x1046842c0.

下面我们绘制一张图来总结一下:


image.png image.png

2、下面我来探讨一下objc_class结构体内部的构造:

image.png

首先我们看一下内部结构:
1、isa指针: 占八个字节
2、superclass: 占八个字节
3、缓存 16个字节
4、bits ,用来存放class_rw_t

rw就是我们平时面试特别爱问的底层东西,请大家认真听一听


image.png image.png

控制台输出如下:


image.png
image.png

最后得到了第一个方法instanceT1(),同学们可以通过相同的方式打印出属性和协议。
同学们有发现方法后面有一个types="@16@0:8",
这个怎么分析呢?

第一个@其实是返回值,代表对象
第二个16是,参数的内存空间
第三个@是,方法的接收者占8个字节,从偏移0开始
第四个:是,方法的实现imp占8个字节,从偏移8开始。

那我们再来分析分析所有的方法,分别有哪些?


image.png

从上面可以看出,一共count=6 有六个方法,打印出来看下分别是什么吧


image.png

有instanceT1(),address(),getAddress(),age(),getAge(),.cxx_destruct(),
前面五个方法没有疑问,但最后一个是什么呢?当类设置成员变量的时候,会默认创建上面的析构函数(ARC模式下面释放成员变量的,属性成功的成员变量同样也会生成析构函数)。
又有同学会问,那类方法instanceT2()到哪里去了呢?
这里给同学们一个研究的机会。

上面为大家介绍了类里面的方法列表,那下面我们再来分析一下属性列表

image.png

通过上面的流程,可以打印出所有属性


image.png

通过以上的学习,我们对今天作一个总结

1、类也是对象,类对象有且只有一个。类的本质是objc_class结构体,里面存了isa指针指向元类、有父类、属性、实例方法、协议、方法缓存等。

2、isa的指向关系
实例对象的isa ---> 类
类的isa --------> 元类
元类的isa --------> 根元类
根元类的isa ----------> 根元类自己

3、元类的继承关系
元类的父类==父类的元类,根元类的父类是根NSObject,NSObject是万物之主

上一篇下一篇

猜你喜欢

热点阅读