上一篇中对isa做了介绍OC底层探索06-isa本身藏了多少信息你知道吗?,下面就来看看isa在oc中的作用是什么?
isa作用
这是一幅iOS开发工程师都非常熟悉的结构图,需要每个人都必须熟记在心
。通过lldb的调试、系统API两种方式,加强对这幅图的理解,巩固记忆。
isa流程
// @interface HRTest : NSObject
HRTest * test = [HRTest alloc];
(lldb) x/gx test
0x1007b8fc0: 0x001d8001000034a5
(lldb) p/x 0x001d8001000034a5 & 0x00007ffffffffff8ULL
(unsigned long long) $0 = 0x00000001000034a0 //对象的类
(lldb) po $0
HRTest
(lldb) p/x test.class
(Class) $1 = 0x00000001000034a0 HRTest //对象的类
通过掩码
获取到shiftcls
里的信息与test.class
地址相等。同样都是指向当前HRTest
类。图中的第一步。
通过这种方式继续往下走:
(unsigned long long) $0 = 0x00000001000034a0 //对象的类
(lldb) po $0
HRTest
(lldb) x/gx 0x00000001000034a0
0x1000034a0: 0x00000001000034c8
(lldb) p/x 0x00000001000034c8 & 0x00007ffffffffff8ULL
(unsigned long long) $2 = 0x00000001000034c8 //类的元类
(lldb) po $2
HRTest
根据当前类继续往下查看,找到了类的元类
。打印当前元类
,虽然得到类的名称,但是0x00000001000034a0
,0x00000001000034c8
地址完全不同,这就是两个类对象
。
- 注意观察两个地址差了40位,猜测:类的大小占40位。(OC底层探索08-基于objc4-781类结构分析会验证)
-
类对象
的isa通过掩码
后,并没有变化证明类对象中除了shiftcls
其他位置都是0并不包含信息。
图中的第二步。
拿到类的元类继续走:
(unsigned long long) $2 = 0x00000001000034c8 //类的元类
0x1000034c8: 0x00007fff997fc0f0
(lldb) p/x 0x00007fff997fc0f0 & 0x00007ffffffffff8ULL
(unsigned long long) $3 = 0x00007fff997fc0f0 //根元类
(lldb) po $3
NSObject
(lldb) p/x NSObject.class //NSObject类对象地址
(Class) $4 = 0x00007fff997fc118
根元类
虽然是NSObject类
,但是与我们代码中使用的NSObject
地址并不相同。$4
虽然是NSOject
但只负责当然元类。
-
对象有多个,但是每个类在内存中都只会存在一份。即使强如NSObject
图中的第三步。
根元类继续:
(unsigned long long) $3 = 0x00007fff997fc0f0 //根元类
(lldb) p/x 0x00007fff997fc0f0 & 0x00007ffffffffff8ULL
(unsigned long long) $5 = 0x00007fff997fc0f0 //还是跟元类
(lldb) po $5
NSObject
验证了根元类指向自己。
图中的第四步。
总结
isa
就是将对象和类,类对象和元类、元类和根元类相互建立关系
网友评论