上一章我们得知isa
存储了类型信息,用isa
的地址 & ISA_MASK
就可以得到类的信息,这一章深入探索一下isa
的走势图
ISA_MASK
= 0x0000000ffffffff8ULL
p/x
:以16进制读取对象的地址
x/4gx
:以16进制形式读取4个8位的内存空间里面存储的值
p/t
:将内存转为2进制
Person * person = [[Person alloc]init];
在person
初始化后,添加断点
- 获取
person
的内存地址
(lldb) p/x person
(Person *) $0 = 0x0000000101a04120
- 得到
person
的isa
指针地址,打印person的类信息
(lldb) x/4gx $0
0x101a04120: 0x001d8001000021d1 0x0000000000000000
0x101a04130: 0x0000000000000000 0x0000000000000000
(lldb) p/x 0x001d8001000021d1 & 0x0000000ffffffff8ULL
(unsigned long long) $1 = 0x00000001000021d0
(lldb) po $1
Person
- 得到了
Person(类)
的信息后,既然万物皆对象,让我们猜测一下,它是否有isa
指针,如果有指向谁呢?
(lldb) x/4gx $1
0x1000021d0: 0x00000001000021a8 0x0000000100333140
0x1000021e0: 0x0000000101a04180 0x0001801000000003
(lldb) p/x 0x00000001000021a8 & 0x0000000ffffffff8ULL
(unsigned long long) $2 = 0x00000001000021a8
(lldb) po $2
Person
- 又得到了个
Person(元类)
,也就是面试总提到的元类
,元类
的isa
指向谁呢?继续打印
(lldb) x/4gx $2
0x1000021a8: 0x00000001003330f0 0x00000001003330f0
0x1000021b8: 0x000000010067a7b0 0x0003e03100000007
(lldb) p/x 0x00000001003330f0 & 0x0000000ffffffff8ULL
(unsigned long long) $3 = 0x00000001003330f0
(lldb) po $3
NSObject
- 我们找到了
NSobject(根元类)
,根元类
的isa
指向谁呢?继续打印
(lldb) x/4gx $3
0x1003330f0: 0x00000001003330f0 0x0000000100333140
0x100333100: 0x0000000100708e70 0x0004e03100000007
-
根元类
的isa
地址跟根元类
的地址是一样的,那是不是随便一个继承于NSObject
的类都各自有各自的根源类呢?我们打印一下Person
的父类,也就是NSObject
的根元类
(lldb) p NSObject.class
(Class) $5 = NSObject
(lldb) p/x NSObject.class
(Class) $6 = 0x0000000100333140 NSObject
(lldb) x/4gx $6
0x100333140: 0x00000001003330f0 0x0000000000000000
0x100333150: 0x000000010067ab70 0x0001801000000003
-
0x00000001003330f0
这个地址又出现了,也就是说根元类
只有一个
此时,我们已经可以得到一个初步的isa
走位图
我们可以尝试再创建一个类继承于Person
,然后观察走势图,就可以得到网络上比较经典的isa
走位图了,偷个懒
Root class(class)
其实就是NSObject
,NSObject
是没有超类的,所以Root class(class)
的 superclass
指向nil
每个Class
都有一个isa指针指向唯一的Meta class
Root class(meta)
的superclass
指向Root class(class)
,也就是NSObject
,形成一个回路
每个Meta class
的isa
指针都指向Root class(metal)
网友评论