iOS 類的數據結構

數據結構

Class 就是結構體 objc_class 數組

內部結構以下,須要注意的是objc_class繼承自objc_object,那麼裏面就應該有一個isa緩存

參數名 類型 做用
isa Class isa指針,指向元類
superclass Class 父類
chache cache_t 方法緩存,大小由內部成員決定
bits class_data_bits_t 存儲了一些數據
data class_rw_t 獲取bits裏存儲的data

一、isa

具體請看 isa詳解數據結構

二、superclass

看變量名就知道這是父類對象,不須要過多解釋app

三、cache 方法緩存

cache顧名思義是緩存 post

參數名 類型 大小 做用
_buckets 數組 8字節 存儲一個個結構體bucket_t
_mask mask_t,實際就是uint32_t 4字節 掩碼
_occupied mask_t,實際就是uint32_t 4字節 已緩存的數量

接下來看bucket_t是什麼,bucket_t有2個成員變量_impkey,這不用多說確定是方法和關鍵值。那麼咱們就能夠猜測,是否是能根據key獲取到對應的IMP,進行方法調用?至此也肯定了cache裏緩存的是方法。 ui

四、bitsdata

能夠看到bits是一個64位的數據段,那麼裏面存了什麼數據呢? 3d

bits下面緊接了一個data的聲明,返回的正是bits裏面的數據。可是類型是class_rw_t指針

4-1 class_rw_t 結構

methods方法、properties屬性、protocols協議,都是咱們日常在聲明類的時候能看到的,感受至關熟悉。可是裏面還有一個class_ro_t類型的成員變量ro引發了個人注意 code

4-2 class_ro_t 結構

ro裏也有方法、屬性、協議,還有實例變量,這是爲何呢? cdn

4-3 探索 class_rw_t

LGPerson以下

執行代碼打印獲取到LGPerson類的結構,能夠直接看到isasuperClass。可是怎麼獲取class_rw_tclass_ro_t 呢?

經過isa地址向右偏移32位能夠獲取到bits

輸出methods,看到數量爲4,存儲了咱們聲明的sayHello方法以及nickNamesetter、getter方法,可是並無看到sayHappy方法?

輸出properties能夠看到咱們聲明的nickName屬性,符合咱們的預期

輸出protrols,裏面是空的,也符合預期

至此,對比LGPerson文件咱們尚未看到sayHappy方法和成員變量hobby,猜想它們又被存儲在哪裏呢?來輸出ro看看

輸出baseMethodList能夠看到裏面的內容和rwmethods是同樣的,沒有sayHappy方法

輸出baseProperties,很惋惜依舊沒有找到hobby

輸出ivars,能夠看到count爲2,單獨輸出之後咱們能夠看到hobby_nickName都在其中

4-四、類方法存儲

sayHappy方法到底去哪裏了?sayHappysayHello 區別在於 sayHello 是實例方法, sayHappy 是類方法。這說明了實例方法存儲在類對象中,類方法不存儲在類對象中。

那麼類方法存在哪裏呢?大膽猜想一下類方法會不會存在元類對象中呢?接下來去元類中尋找一下。

輸出元類的方法列表

4-五、bitsro數據重複問題

bits裏面存儲了方法列表、屬性列表等成員變量,爲何還須要ro再存儲一份?

objc_class結構中的data()方法能夠返回bits的信息,那麼咱們即可以經過setData()向上查找調用方看看class賦值流程,也許就能解開這個問題。

找到編譯期間執行的realizeClass方法,這裏應該就是最初的地方。 但這裏並無對rw裏面的列表賦值,編譯期間rw的各個列表應該是空值!

那麼rw的數據又是從哪裏來的呢?這就涉及到了methodizeClass方法,就是它向rw中添加類的方法列表、協議列表、屬性列表。

執行了methodizeClassro中的屬性、對象方法,協議都添加到了rw中。這樣在class_rw_t結構中能夠拿到類的相關信息了。也就造成了如下結構:

雖然找到了實現,可是仍是不知道爲何這麼存呀。這就須要看看了realizeClass在何時調用了。這個時候,prepare_load_methods引發了個人注意

prepare_load_methods是加載分類時會調用的方法,結合methodizeClass咱們會發現分類添加的方法通通都會加入到rw而不加入roro保留着類最原始的數據,後續改變都沒法侵入它!

總結

至此,疑問已經解開,類結構已經解析完畢。

結論以下:

  • .h文件聲明屬性會自動生成settergetter、成員變量。
  • 實例方法存在類中,類方法存在元類中
  • 原始方法會存在ro中,分類方法存在rw
相關文章
相關標籤/搜索