iOS小知识之isa走位图

1,214 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

在之前的文章中我们知道了实例对象的isa指向类,类的isa指向它的元类,那么元类的isa又会指向谁呢? 为了探索,在main文件中写下如下简单代码:

LGPerson *p = [LGPerson alloc];
NSLog(@"%@",p);

可以得到实例对象的信息,就可以得到实例对象的isa

x/4gx p
--------------------
0x1005ad990: 0x011d800100008365 0x0000000000000000
0x1005ad9a0: 0x0000000000000000 0x0000000000000000

因为实例对象的isa指向类,对实例对象的isa进行& 0x00007ffffffffff8 操作,得到类的 地址,就可以获取到类信息

p/x 0x011d800100008365 & 0x00007ffffffffff8 
--------------------------------------
0x0000000100008360
--------------------------------------
x/4gx 0x0000000100008360

0x100008360: 0x0000000100008338 0x00007fff807c2088
0x100008370: 0x000000010060f430 0x0001802c0000000f
---------
//通过类的isa进行& 0x00007ffffffffff8操作,获取元类的信息
p/x 0x0000000100008338 & 0x00007ffffffffff8
(long) $2 = 0x0000000100008338

打印元类的数据结构

x/4gx 0x0000000100008338**

0x100008338: 0x00007fff807c2060 0x00007fff807c2060
0x100008348: 0x000000010060eed0 0x0001e03500000003


  • 元类isa0x00007fff807c2060 元类isa进行&运算
p/x 0x00007fff807c2060 & 0x00007ffffffffff8

(long) $3 = 0x00007fff807c2060

  • 得到相同的地址 将地址进行po打印
po 0x00007fff807c2060
NSObject

发现元类的isa指向NSObject 查看NSObject类的地址

p/x NSObject.class
(Class) $5 = 0x00007fff807c2088 NSObject
  • 地址和LGPerson元类isa指向的NSObject地址不同 那么问题来了,元类的isa指向的地址到底是什么呢? 打印NSObject类的数据结构
x/4gx 0x00007fff807c2088
------------------------------------
0x7fff807c2088: 0x00007fff807c2060 0x0000000000000000
0x7fff807c2098: 0x00000001005a7d00 0x0002801000000003
  • NSObject作为根类,它的isa指向的元类,称之为根元类
  • 根元类的地址和LGPerson元类isa指向的地址相同
  • LGPerson的元类isa,指向的并不是NSObject,而是根元类(NSObject的元类) 打印根元类的数据结构
x/4gx 0x00007fff807c2060
----------------------------------
0x7fff807c2060: 0x00007fff807c2060 0x00007fff807c2088
0x7fff807c2070: 0x00000001005addc0 0x0003e03100000007
  • 发现根元类的isa指向自己 由此,我们可以得出如下结论:
  • 实例对象的isa指向类,类的isa指向元类,元类的isa指向根元类,而根元类的isa指向它自己(根元类)
  • NSObject作为根类,isa走位只有两层
  • 根类的isa指向根元类,根元类的isa指向它自己(根元类)

可参考苹果官方给出的isa走位图(虚线部分) isa流程图.png