當前位置:
首頁 > 知識 > 「OC底層」OC對象本質,如 isa, super-class

「OC底層」OC對象本質,如 isa, super-class

1、我們編寫的Objective-C,底層現實都是C/C++,代碼生成步驟如下:

「OC底層」OC對象本質,如 isa, super-class

2、在OC中的所有面向對象的實現,都是基於C/C++的數據結構實現的

3、將Objective-C代碼轉換為CC++代碼

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 輸出的CPP文件

注:如果需要鏈接其他框架,使用-framework參數。比如-framework UIKit

一個OC對象在內存中是如何布局的?

NSObject基類的實現:

「OC底層」OC對象本質,如 isa, super-class

子類的實現:

「OC底層」OC對象本質,如 isa, super-class

子類的拆解:

「OC底層」OC對象本質,如 isa, super-class

1、在OC中的對象,就是 C++中的 struct來實現的

2、每個OC對象中都會有一個 isa 的指針,isa指向的是 objc_class 結構體,如下:

「OC底層」OC對象本質,如 isa, super-class

通過代碼可以看得出在OC2 中已經不能通過 objc_method_list 之類的方式獲取方法名、實例、協議之類的了,需要使用新的方法獲取

思路:自定義一個和oc源碼中 objc_class 結構一樣的結構體,然後將對象的isa 強轉成我們自定義的那個,再去調用

如下是OC中objc_class的源碼:

「OC底層」OC對象本質,如 isa, super-class

新的OC版本中方法、屬性、協議相關數據都存在了 bits

通過 bits.data() 返回 class_rw_t 結構,如下:

「OC底層」OC對象本質,如 isa, super-class

bits.data() 的實現:

「OC底層」OC對象本質,如 isa, super-class

「OC底層」OC對象本質,如 isa, super-class

其中需要 通過 & FAST_DATA_MASK 才能獲取到真實的地址

OC對象的分類

Objective-C對象主要分為以下3類:

1> instance對象(實例對象)

2> class對象(類對象)

3> meta-class對象(元類對象)

通過下面的代碼可以分別獲取3種對象:

NSObject* obj = [[NSObject alloc]init];
const char* className = [@"NSObject" cStringUsingEncoding:NSUTF8StringEncoding];

// 實例對象
NSLog(@"instance: %p",obj);

// 類對象
NSLog(@"NSObject class: %p", [NSObject class]);
// 同上
NSLog(@"obj class: %p", [obj class]);
// 如果傳實例對象,獲取到的還是類對象
NSLog(@"get class: %p", object_getClass(obj));
// 通過類名獲取類對象
NSLog(@"objcClass: %p", objc_getClass(className));

// 元類對象
// 必需要傳入類對象才能獲取元類對象
NSLog(@"meta-class: %p", object_getClass([obj class]));
// 通過類名獲取元類對象
NSLog(@"objcMetaClass: %p", objc_getMetaClass(className));

// 判斷是否是metaClass
NSLog(@"isMetaClass1:%i",class_isMetaClass([NSObject class]));  // 0
NSLog(@"isMetaClass2:%i",class_isMetaClass([[NSObject class] class])); // 0
NSLog(@"isMetaClass3:%i",class_isMetaClass(object_getClass([NSObject class]))); // 1

輸出:

2018-09-27 14:39:37.363 OC_isa_supclass[1350:102454] instance: 0x100202b50
2018-09-27 14:39:37.364 OC_isa_supclass[1350:102454] NSObject class: 0x7fff760140f0
2018-09-27 14:39:37.364 OC_isa_supclass[1350:102454] obj class: 0x7fff760140f0
2018-09-27 14:39:37.364 OC_isa_supclass[1350:102454] get class: 0x7fff760140f0
2018-09-27 14:39:37.365 OC_isa_supclass[1350:102454] objcClass: 0x7fff760140f0
2018-09-27 14:39:37.365 OC_isa_supclass[1350:102454] meta-class: 0x7fff76014118
2018-09-27 14:39:37.365 OC_isa_supclass[1350:102454] objcMetaClass: 0x7fff76014118
2018-09-27 14:49:27.746 OC_isa_supclass[1360:106109] isMetaClass1:0
2018-09-27 14:49:27.746 OC_isa_supclass[1360:106109] isMetaClass2:0
2018-09-27 14:49:27.746 OC_isa_supclass[1360:106109] isMetaClass3:1

1> 需要注意的是 objc_getClass 方法,當傳入的是實例對象,就會返回類對象,如果傳入的是類對象就會返回元類對象

2> 還有一點就是 [[NSObject class] class] 這樣是獲取不到元類對象的,這樣獲取到的還是類對象

3> 另外裡面還有兩個 objc_ 開頭的方法,分別是獲取類對象和元類對象,但它是傳入類名字元串就可以了,需要轉換成 C語言的char

1、instance對象

instance對象就是通過類alloc出來的對象,每次調用alloc都會產生新的instance對象

「OC底層」OC對象本質,如 isa, super-class

object1、object2是NSObject的instance對象(實例對象)

它們是不同的兩個對象,分別佔據著兩塊不同的內存

「OC底層」OC對象本質,如 isa, super-class

「OC底層」OC對象本質,如 isa, super-class

instance對象在內存中保存的信息包括:

1> isa指針

2> 其它成員變數

2、class對象

「OC底層」OC對象本質,如 isa, super-class

objectClass1 ~ objectClass5都是NSObject的class對象(類對象)

NSObject類對象只有一個,所有實例對象的class屬性獲取到的都是同一個類對象

class對象在內存中存儲的信息主要包括:

1> isa指針

2> superclass指針

3>類的屬性信息(@property)、類的對象方法信息(instance method)

4> 類的協議信息(protocol)、類的成員變數信息(ivar)

....

3、meta-class對象

「OC底層」OC對象本質,如 isa, super-class

objectMetaClass是NSObject的meta-class對象(元類對象)

每個類在內存中有且只有一個meta-class對象

meta-class對象在內存中存儲的信息主要包括:

1> isa指針

2> superclass指針

3> 類的類方法信息(class method)

...

註:class 對象和 meta-class 對象都是 Class 類型的,它們其實結構都是一樣的,class對象中一樣會包含 類方法,只不過那個類方法是 空的而已。

同樣,meta-class對象中也有 類的屬性、對象方法、協議、成員變數,不過那些對應的值也都是空

isa指針

上面我們通過源碼可以看到每個對象都有一個 isa 指針,isa指針作用是幹嘛的呢?

「OC底層」OC對象本質,如 isa, super-class

通過上圖可以看出:

1> instance的isa指向class

當調用對象方法時,通過instance的isa找到class,最後找到對象方法的實現進行調用

2> class的isa指向meta-class

當調用類方法時,通過class的isa找到meta-class,最後找到類方法的實現進行調用

class對象的superclass指針

superclass是用於找父類的,比如子類調用某個方法,如果子類中沒有,就會去父類找,底層就是通過superclass找到父類的,如下圖:

「OC底層」OC對象本質,如 isa, super-class

當Student的instance對象要調用Person的對象方法時,會先通過isa找到Student的class,然後通過superclass找到Person的class,最後找到對象方法的實現進行調用

meta-class對象的superclass指針

meta-class中的superclass基本和 class對象中的一樣,不過有一點點區別,如圖:

當Student的class要調用Person的類方法時,會先通過isa找到Student的meta-class,然後通過superclass找到Person的meta-class,最後找到類方法的實現進行調用

有什麼區別呢?從這圖可能看不出來,區別就是如果基類的meta-class中都找不到類方法,那麼它就會去從基類對象裡面去找對象方法,OC的底層其實是不區分 對象方法與類方法的。

isa、superclass總結

「OC底層」OC對象本質,如 isa, super-class

這張圖能夠清楚的描述 isa和superclass的作用和關係,下面是備註了一下,看得更加懂點。

「OC底層」OC對象本質,如 isa, super-class

  • instance的isa指向的是class對象
  • class的isa指向的是meta-class對象
  • meta-class的isa指向的是基類的meta-class對象
  • class的superclass指向的是父類的class對象,如果沒有父類,superclass指針為nil
  • meta-class的superclass指向的是父類的meta-class對象
  • 基類的meta-class指向的是基類的class對象(重點)

instance調用對象方法的軌跡:

實例對象會先通過isa找到class對象,判斷裡面有沒有要調用的方法,如果有就直接調用,沒有就會通過class對象中的superclass找到父類,然後在父類中判斷是否有該方法,如果還沒有就接著往上找。

class調用類方法的軌跡:

isa找meta-class,方法不存在,就通過superclass找父類,最後基類mate-class也沒有的話還會去基類對象找

isa指針的一些問題

上面已經說到了instance對象的isa指針指向的是class對象,那就是說instance對象的isa指針內存地址是不是就是class對象的內存地址呢?

如果在以前的32位系統中確實如此,在64位系統中不是的,裡面有一個點操作, ISA_MASK

「OC底層」OC對象本質,如 isa, super-class

其中arm64和x86架構的這個 ISA_MASK的偏移地址是不一樣的,如下圖:

「OC底層」OC對象本質,如 isa, super-class

class、meta-class對象的本質結構都是struct objc_class,如下圖:

「OC底層」OC對象本質,如 isa, super-class

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

windows離線狀態下源碼安裝Robotframework 環境及依賴包
django載入css文件和圖片

TAG:程序員小新人學習 |