[iOS底层]-类、元类、根元类的isa关系和继承关系

2020/9/12 posted in  iOS底层 总阅读量

类、元类、根元类中isa的关系

首先我们在main.m文件中创建几个LJPerson对象进行分析。


通过po指令和x/4gx获取实例对象O、O2的地址和isa地址:

/********** 实例对象O ********/
(lldb) po O
<LJPerson: 0x100616e60>

(lldb) x/4gx O
0x100616e60: 0x001d800100002181 0x0000000000000000
0x100616e70: 0x0000000100610f80 0xd4ed0b2ccdb72417

/********** 实例对象O2 ********/
(lldb) po O2
<LJPerson: 0x1006063b0>

(lldb) x/4gx O2
0x1006063b0: 0x001d800100002181 0x0000000000000000
0x1006063c0: 0x0000000100335f40 0x0000000100809c00

可以发现O、O2的实例对象地址不一样,isa的地址是一样的,都指向0x001d800100002181。我们通过 & ISA_MASK 0x0000000ffffffff8ULL得到isa(shiftcls段)所指向的类。

(lldb) po 0x001d800100002181 & 0x00007ffffffffff8
LJPerson

发现打印出了LJPerson,我们知道类也是一个对象,类对象,我们如何验证isa指向的这个LJPerson就是类对象呢?

// 打印isa指针地址
(lldb) p/x 0x001d800100002181 & 0x00007ffffffffff8
(long) $10 = 0x0000000100002180

// 打印LJPerson.class指针地址
(lldb) p/x LJPerson.class
(Class) $15 = 0x0000000100002180 LJPerson

可以看出isa的指针地址和LJPerson类的指针地址一模一样,由此证明isa就是指向的LJPerson类。

既然LJPerson也是一个对象,那它应该也有isa,接下来我们就来探讨一下。

(lldb) x/4gx LJPerson.class
0x100002180: 0x0000000100002158 0x0000000100334140
0x100002190: 0x0000000100788c10 0x0004801000000007

(lldb) po 0x0000000100002158 & 0x00007ffffffffff8

(lldb) p/x 0x0000000100002158 & 0x00007ffffffffff8
(long) $2 = 0x0000000100002158
LJPerson

打印出isa的值,发现也是LJPerson,而且isa的地址为0x0000000100002158LJPerson类对象地址还不一样,这个是什么呢?这个就是元类元类保存类对象的方法(类方法),属性等。

我们继续查看一下元类isa

(lldb) x/4gx 0x0000000100002158
0x100002158: 0x00000001003340f0 0x00000001003340f0
0x100002168: 0x00000001040040a0 0x0004e03100000007

(lldb) po 0x00000001003340f0 & 0x00007ffffffffff8
NSObject

(lldb) p/x 0x00000001003340f0 & 0x00007ffffffffff8
(long) $20 = 0x00000001003340f0

发现元类isa指向了NSObject,这个时候我们就要思考一下问题,这个NSObject是对象,还是元类呢?

(lldb) p/x NSObject.class
(Class) $5 = 0x0000000100334140 NSObject

(lldb) x/4gx 0x0000000100334140
0x100334140: 0x00000001003340f0 0x0000000000000000
0x100334150: 0x0000000102928ea0 0x0002801000000003

我们通过打印地址发现,LJPerson元类的isa指向的NSObject元类

(lldb) x/4gx 0x00000001003340f0
0x1003340f0: 0x00000001003340f0 0x0000000100334140
0x100334100: 0x0000000100735aa0 0x0005e03100000007

再查看一下NSObject元类的isa地址,发现指向的是自己。

流程如下图所示:

isa指向结论如下图所示:

对象、类、元类继承关系

  1. 实例对象之间没有继承关系。
  2. 类之间存在继承关系:
    • 子类(SubClass)继承自父类(SuperClass)
    • 父类(SuperClass)继承根类(RootClass),根类也就是NSObject
    • 根类继承nil
  3. 元类(meta class)也存在继承关系:
    • 子类的元类(meta SubClass)继承自父元类(meta SuperClass)
    • 父元类(meta SuperClass)继承根元类(meta RootClass)
    • 根元类继承根类(RootClass)