底层原理:isa和superclass

2022-02-27  本文已影响0人  飘摇的水草

OC的每个对象中都会有一个isa指针,每个类中都会有一个superclass指针,那么它们有什么用?实例对象,类对象,元类对象之间又有什么联系呢?

isa指针
  1. 对象的isa 指向哪里?

首先我们准备一个继承自NSObject的JJPerson类,定义一个对象方法和一个类方法,然后我们分别调用这两个方法。

类方法实际在元类对象中而不是类中,对象方法实际存放在类对象中而不是实例对象中,那它们分别是怎么调用到并没有存放在自身的东西呢?这时候就是isa指针发挥作用了。

如上图所示:

class对象的superclass指针

我们把问题变得稍微复杂一些,我们为JJPerson增加一个子类JJStudent,同样顺手为它准备一个对象方法和一个类方法。

正如我们所知,student继承自person,它是可以调用父类的方法的。

但是Person的对象方法和类方法都是存放在Person的类对象和元类对象中,Student的类和实例对象是怎么调用它们的呢?这样的情况下isa指针看起来已经不能满足我们的需求了,那这时候就需要superclass指针。

isa和superclass总结

这张经典的图相信很多iOS开发者都看过,它很好地指出了isa和superclass在OC对象之间所担任的联系

综合我们上面提到的例子,我们可以为这张图加上备注方便理解

总结如下:

isa细节

前面我们提到,在OC对象中实例对象的isa是指向类对象,类对象的isa指向元类对象,这样我们可以通过isa把OC中的三种对象联系起来。那么,isa是怎么实现的呢?实例对象的isa直接存放着类对象的地址,类对象的isa直接存放元类对象的地址吗?


在控制台可以通过以下命令来查看对象的isa指针:

(1ldb) p person–>isa
(Class) $0 = MJPerson

如果想要看isa的地址值可以通过强转的方式:

(1ldb) p (long)person->isa
(1ong) S1 = 8303516187936969

这样输出的地址值是十进制的,通过下面命令可以输出十六进制的地址值:

(11db) p/x (long)person->isa
(1ong) S2 = 8x801d8001000014c9

那么实例对象是怎么通过isa来找到类对象的呢?这里就不得不提一个ISA_MASK的东西,我们还是从源码寻找答案。

分析

其实这个问题不难解决,因为我们可以看到objc_class的结构,那么我们可以定义一个和它一样的结构体来获取isa

这也证明了,我们OC对象中的isa并不是直接存放所指向对象的地址值,而是需要通过和ISA_MASK进行一次位运算才能得出真实地址。

上一篇 下一篇

猜你喜欢

热点阅读