一浆劲、回顧
上一期OC底層原理05-isa結(jié)構(gòu)分析中,我們?cè)?code>GomuPerson的實(shí)例對(duì)象person
的地址中止邮,拿到第一位地址中的isa
温技,進(jìn)行逆向推導(dǎo)isa
&mask
得到GomuPerson
類
//: 第一步,拿到`person`的內(nèi)存地址
(lldb) x/4gx person
//: 或者
(lldb) p person
(GomuPerson *) $31 = 0x0000000100632a50
(lldb) x/4gx 0x0000000100632a50
//: 兩種方式都能拿到`person`的地址
//: 下面的`0x001d800100002465 `就是我們需要的`isa`
0x100632a50: 0x001d800100002465 0x0000000000000000
0x100632a60: 0x0000000000000000 0x0000000000000000
//: 用`isa` & `mask`
(lldb) p/x 0x001d800100002465 & 0x00007ffffffffff8ULL
//: 得到了`GomuPerson `的16進(jìn)制地址
(unsigned long long) $29 = 0x0000000100002460
//: 得到`GomuPerson `
(lldb) po 0x0000000100002460
GomuPerson
二廊移、isa流程探索
既然我們用x/4gx
打印person
對(duì)象的地址糕簿,找到isa
探入,從而拿到GomuPerson
,那我們用x/4gx
打印GomuPerson
的地址懂诗,它會(huì)有isa
嗎蜂嗽?而它的isa
又會(huì)拿到什么?
2.1 類的isa
的指向
//: 拿到`GomuPerson `的內(nèi)存地址
(lldb) x/4gx 0x0000000100002460
0x100002460: 0x0000000100002438 0x0000000100334140
0x100002470: 0x0000000100632a80 0x0002803400000003
//: `isa` & `mask`
(lldb) p/x 0x0000000100002438 & 0x00007ffffffffff8ULL
(unsigned long long) $32 = 0x0000000100002438
//: 又得到了`GomuPerson`
(lldb) po 0x0000000100002438
GomuPerson
-
對(duì)象的isa
->類
(person -> GomuPerson)殃恒,類的isa
->?
(GomuPerson的isa -> GomuPerson ) -
對(duì)象
和類
都有isa
植旧,說明類也是對(duì)象
-
OC底層原理01-alloc流程探索中已經(jīng)知道了,
類對(duì)象
在內(nèi)存中只會(huì)存一份
离唐,但是這里po 0x0000000100002438
和po 0x0000000100002460
都能拿到GomuPerson
病附,注意這里第二次打印的GomuPerson
是元類
-
元類的定義和創(chuàng)建
是由編譯器自動(dòng)完成
- 得出
isa
的流程對(duì)象的isa
->類的isa
->元類
2.2 元類的isa
的指向
//: 拿到`GomuPerson `元類的內(nèi)存地址
(lldb) x/4gx 0x0000000100002438
0x100002438: 0x00000001003340f0 0x00000001003340f0
0x100002448: 0x00000001010045e0 0x0005e03500000007
//: `isa` & `mask`
(lldb) p/x 0x00000001003340f0 & 0x00007ffffffffff8ULL
(unsigned long long) $34 = 0x00000001003340f0
//: 得到`NSObject `
(lldb) po 0x00000001003340f0
NSObject
-
元類的isa
指向了NSObject
- 得出
isa
的流程對(duì)象的isa
->類的isa
->元類的isa
->NSObject
2.3 NSObject的isa
的指向
//: 拿到`NSObject `的內(nèi)存地址
(lldb) x/4gx 0x00000001003340f0
0x1003340f0: 0x00000001003340f0 0x0000000100334140
0x100334100: 0x0000000101059460 0x0005e03100000007
//: `isa` & `mask`
(lldb) p/x 0x00000001003340f0 & 0x00007ffffffffff8ULL
(unsigned long long) $36 = 0x00000001003340f0
//: 又得到`NSObject `
(lldb) po 0x00000001003340f0
NSObject
-
NSObject
又指向了NSObject
- 兩個(gè)
NSObject
的地址都是0x00000001003340f0
,說明這里的NSObject的isa
會(huì)指向自己 - 得出
isa
的流程對(duì)象的isa
->類的isa
->元類的isa
->NSObject的isa
->NSObject
2.4 這里的NSObject
和系統(tǒng)初始化的NSObject
的區(qū)別
//: 獲取系統(tǒng)初始化的`NSObject `的地址
(lldb) p/x NSObject.class
(Class) $43 = 0x0000000100334140 NSObject
//: 拿到系統(tǒng)初始化的`NSObject `的`isa`
(lldb) x/4gx 0x0000000100334140
0x100334140: 0x00000001003340f0 0x0000000000000000
0x100334150: 0x0000000100632d90 0x0001801000000003
- 系統(tǒng)初始化的
NSObject
的isa
指向了0x00000001003340f0
亥鬓,和我們上面獲取到的NSObjcet
的地址相同 -
GomuPerson
元類的isa指向的NSObject
完沪,不是系統(tǒng)的NSObjcet
,而是系統(tǒng)的NSObjcet
的元類
嵌戈,即根元類
- 得出
isa
的流程對(duì)象的isa
->類的isa
->元類的isa
->根元類的isa
->根元類
- 萬物皆對(duì)象覆积,皆有
isa
2.5 打印對(duì)象地址驗(yàn)證流程
// 實(shí)例對(duì)象
GomuPerson *person = [GomuPerson alloc];
// 類
Class class = object_getClass(person);
// 元類
Class metaClass = object_getClass(class);
// 根元類
Class rootMetaClass = object_getClass(metaClass);
// 根根元類
Class rootRootMetaClass = object_getClass(rootMetaClass);
NSLog(@"\n%p 實(shí)例對(duì)象\n%p 類\n%p 元類\n%p 根元類\n%p 根根元類",person,class,metaClass,rootMetaClass,rootRootMetaClass);
//: 輸出
0x10066fe20 實(shí)例對(duì)象
0x100002470 類
0x100002448 元類
0x1003340f0 根元類
0x1003340f0 根根元類
2.6 isa
流程圖
9491599893819_.pic_hd.jpg
三、繼承流程圖
- 實(shí)例對(duì)象沒有繼承關(guān)系熟呛,繼承關(guān)系來自于類
-
GomuBoy
繼承于GomuPerson
-
person1
宽档,person2
是GomuPerson
的實(shí)例對(duì)象 -
boy1
,boy2
是GomuBoy
的實(shí)例對(duì)象 -
boy1
庵朝,boy2
與person1
雌贱,person2
沒有繼承關(guān)系
-
- 類和元類才有繼承關(guān)系
-
NSObject
繼承于nil
-
根元類
繼承于NSObject
image.png
四、將isa流程圖偿短,和繼承流程圖結(jié)合得出
isa流程圖.png