日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【OC底层】OC对象本质,如 isa, super-class

發(fā)布時間:2025/3/17 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【OC底层】OC对象本质,如 isa, super-class 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Objective-C的本質(zhì)

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

2、在OC中的所有面向?qū)ο蟮膶崿F(xiàn),都是基于C/C++的數(shù)據(jù)結構實現(xiàn)的

3、將Objective-C代碼轉(zhuǎn)換為C\C++代碼

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

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

?

一個OC對象在內(nèi)存中是如何布局的??

?

NSObject基類的實現(xiàn):

?

子類的實現(xiàn):

?

子類的拆解:

?1、在OC中的對象,就是 C++中的 struct來實現(xiàn)的

?2、每個OC對象中都會有一個 isa 的指針,isa指向的是 objc_class 結構體,如下(舊版OC原碼):

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

?

思路:自定義一個和oc源碼中?objc_class 結構一樣的結構體,然后將對象的isa 強轉(zhuǎn)成我們自定義的那個,再去調(diào)用

如下是OC中objc_class的源碼(新版OC原碼):

新的OC版本中方法、屬性、協(xié)議相關數(shù)據(jù)都存在了?bits?

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

bits.data() 的實現(xiàn):

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

整體數(shù)據(jù)結構圖:

?

?

?

?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));// 判斷是否是metaClassNSLog(@"isMetaClass1:%i",class_isMetaClass([NSObject class]));  // 0NSLog(@"isMetaClass2:%i",class_isMetaClass([[NSObject class] class])); // 0NSLog(@"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> 需要注意的是?object_getClass 方法,當傳入的是實例對象,就會返回類對象,如果傳入的是類對象就會返回元類對象

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

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

1、instance對象

instance對象就是通過類alloc出來的對象,每次調(diào)用alloc都會產(chǎn)生新的instance對象 object1、object2是NSObject的instance對象(實例對象)

  它們是不同的兩個對象,分別占據(jù)著兩塊不同的內(nèi)存

?

? instance對象在內(nèi)存中保存的信息包括:

  1> isa指針

  2> 其它成員變量

2、class對象

?

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

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

? ?class對象在內(nèi)存中存儲的信息主要包括:

  1> isa指針

  2> superclass指針

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

  4>?類的協(xié)議信息(protocol)、類的成員變量信息(ivar)

    ....

3、meta-class對象

  

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

?  每個類在內(nèi)存中有且只有一個meta-class對象

?

  meta-class對象在內(nèi)存中存儲的信息主要包括:

?  1> isa指針

   2> superclass指針

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

    ...?

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

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

?

isa指針

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

通過上圖可以看出:

  1> instanceisa指向class
    當調(diào)用對象方法時,通過instanceisa找到class,最后找到對象方法的實現(xiàn)進行調(diào)用

  2> classisa指向meta-class

   ?當調(diào)用類方法時,通過classisa找到meta-class,最后找到類方法的實現(xiàn)進行調(diào)用

?

class對象的superclass指針

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

?當Studentinstance對象要調(diào)用Person的對象方法時,會先通過isa找到Studentclass,然后通過superclass找到Person的class,最后找到對象方法的實現(xiàn)進行調(diào)用

??

?meta-class對象的superclass指針

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

?

  當Student的class要調(diào)用Person的類方法時,會先通過isa找到Student的meta-class,然后通過superclass找到Person的meta-class,最后找到類方法的實現(xiàn)進行調(diào)用

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

?

isa、superclass總結?

?

?

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

?

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

  instance調(diào)用對象方法的軌跡:

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

?  class調(diào)用類方法的軌跡:

   isa找meta-class,方法不存在,就通過superclass找父類,最后基類mate-class也沒有的話還會去基類對象找,這樣就會導致調(diào)用類方法可能會去調(diào)用實例對象的方法

?

?isa指針的一些問題

?上面已經(jīng)說到了instance對象的isa指針指向的是class對象,那就是說instance對象的isa指針內(nèi)存地址是不是就是class對象的內(nèi)存地址呢?

?如果在以前的32位系統(tǒng)中確實如此,在64位系統(tǒng)中不是的,里面有一個點操作, ISA_MASK

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

?

?

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

  

-----------------------------

本文參考借鑒MJ的教程視頻,非常感謝.

轉(zhuǎn)載于:https://www.cnblogs.com/xgao/p/9708163.html

新人創(chuàng)作打卡挑戰(zhàn)賽發(fā)博客就能抽獎!定制產(chǎn)品紅包拿不停!

總結

以上是生活随笔為你收集整理的【OC底层】OC对象本质,如 isa, super-class的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。