iOS探索:Runtime之基本數據結構

objc_object

國際慣例,流程圖 算法

WX20181211-150059@2x.png

  • 首先平時咱們所使用的對象都是id類型的,id對應到runtime中就是objc_object這樣的一個結構體,在這個結構體當中主要包含如下幾個部分:數組

    一、第一部分是isa_t,實際上呢isa_t是一個共用體緩存

    二、在objc_object中還包含了關於isa操做相關的方法,好比說經過objc_object這個結構體來獲取isa所指向的類對象,經過類對象的isa指針獲取它的元類對象數據結構

    三、還包含了一些弱引用相關的一些方法,好比說標記一個對象它是否有過弱引用指針架構

    四、還有關於關聯對象的一些方法,好比說爲一個對象咱們設置一些關聯屬性,關於關聯屬性的一些方法也體如今objc_object這個結構體中函數

    五、最後還包括內存管理相關的一些方法,好比說咱們再MRC下常用到的retain和relese方法,包括MRC和ARC下面均可以用到的autorelesepool(自動釋放池),這些關於內存管理相關的方法都是封裝在objc_object這個結構體中3d

objc_class

WX20181211-151829@2x.png

  • 咱們在OC語言中所使用的Class,表明的是一個類,在runtime中對應的是objc_class這樣一個結構體,它繼承自objc_object,那麼問題來了:Class這樣一個類,它是不是一個對象呢?答案固然是確定的,咱們稱之爲類對象,由於它繼承自objc_object指針

  • 在objc_class這個結構體中,包含superClass這樣一個指針,它指向的也是一個Class,例如:若是這個Class是一個類對象,那麼它的superClass指針指向的事它的父類對象,一個類對象與它的父類對象也正是經過這個superClass指針來創建起聯繫cdn

  • 接下來它還包含一個cache_t這樣一個成員變量,cache_t它表達了方法緩存的一個結構,咱們在進行消息傳遞的時候會使用到對於方法緩存的這樣一個數據結構對象

  • 第三個是關於class_data_bits_t這樣的一個數據結構,實際上咱們對於一個類所定義的變量,屬性,包括它的一些方法都在bits這樣一個數據結構當中

isa指針

共用體isa_t

WX20181211-153729@2x.png

  • isa的結構主要是C++中的共用體,咱們在OC當中其實是定義成了一個isa_t這樣一個名稱,對於一個共用體來講,不論它是在64位架構仍是在32位架構上面,它實際上都是32個0或者1的數字(或者64個0或者1的數字)

  • isa指針主要分爲兩種:一種是指針型isa,另外一種是非指針型isa

  • 指針型isa:isa的值表明的是Class的地址,也就是64個(或者32,看架構)0或者1它的總體內容所表明的是所指向的Class的地址

  • 非指針型isa:isa的值的部分表明的是Class的地址,好比說針對64位架構來講,可能對應的是某一部分33位或者44位所表明的值,並非整個64位都表明,這樣作的一個目的是咱們在尋址過程當中只有三四十位的位數就能夠保證咱們找到全部Class的地址,多出來的這些位能夠用來保存其餘的內容,達到節省內存的目的

isa的指向

  • 關於對象,isa指向的是其類對象

  • 關於類對象,isa指向的是其元類對象

cache_t

  • 用於快速查找方法執行函數 例如咱們在調用一個方法的時候,若是這個方法已經緩存,咱們就不用去其對應的方法列表中遍歷查找,從而節省時間

  • 可增量擴展的哈希表結構 增量擴展體如今當咱們這個結構存儲量在擴大的時候會它也會逐漸的擴大它的內存結構用哈希表來實現也是爲了提升查找效率

  • 局部性原理的最佳應用 例如咱們在調用方法的時候,其實每次調用的都是某幾個方法,若是把這些調用頻率較高的方法放到方法緩存中,那麼下次調用的命中就會更高

WX20181211-160428@2x.png

  • cache_t其實能夠理解爲一個數組來實現的,數組當中都是bucket_t這樣的一個結構體來封裝的

  • 對於bucket_t它有兩個重要的成員變量,一個是key,一個是IMP,對於key其實是OC語言中的selector,在調用一個方法的時候它其實是一個選擇器SEL,對應的就是這裏面的key,咱們能夠經過一個方法選擇器的名稱來尋找一個方法的具體實現。IMP咱們能夠理解爲一個無類型的函數指針

  • 好比說如今咱們拿到一個key,咱們能夠經過哈希查找算法來定位當前這個key所對應的bucket_t這個結構體位於數組中的哪一個位置,咱們定位到這個位置後咱們就能夠提取其中的IMP指針指向的具體函數實現來調用這個函數

class_data_bits_t

  • class_data_bits_t主要是對class_rw_t的封裝

  • class_rw_t表明了類相關的讀寫信息(好比說咱們給類添加的分類中的一些方法,或者屬性以及協議)、對class_ro_t的封裝

  • class_ro_t表明了類相關的只讀信息

class_rw_t

WX20181211-162348@2x.png

  • class_rw_t主要包含class_ro_t、protocols(協議)、properties(屬性)、methods(方法列表),對於協議,屬性和方法列表的數據結構是二維數組

class_ro_t

WX20181211-163241@2x.png

  • class_ro_t主要包含name(名字)、ivars(成員變量)、protocols(協議)、properties(屬性)、methodList(方法列表),對於成員變量、協議、屬性和方法列表的數據結構是一維數組,與class_rw_t的區別在:在class_rw_t中通常存放的是分類的一些內容,而在class_ro_t中通常存放類原始的一些內容和信息(我的理解)

method_t

WX20181211-164853@2x.png

  • method_t是一個結構體類型,主要包括SEL類型的name(方法的名稱)、types(對應的是函數的返回值和參數的組合)、IMP類型的imp(無類型的函數指針,對應函數體)

Type Encodings

WX20181211-165508@2x.png

  • const char* types是一個不可變得字符指針,它的組成結構如上圖所示,首先第一位是返回值,後面是參數,**爲啥第一位置是返回值呢?**由於咱們定義一個函數的時候,函數的參數能夠有多個,可是返回值只能有一個,若是沒有返回值,那麼返回值的類型能夠用void來修飾,因此返回值佔據types中的第一個位置

  • 舉個栗子,例如在OC中- (void)aMethod;這個方法,它的返回值是void類型的,沒有參數,它對應的types就是v@:

  • 首先v對應的事返回值(void類型),@對應的是參數1(id類型),:對應的事參數2(SEL),這個解釋一下:當咱們調用一個方法或者說是方法消息傳遞時到runtime層面會轉化成調用objc_msgSend方法,這個函數中的第一個參數和第二個參數是不可變的(固定的),第一個參數必須是id類型的,及消息的接受者(self),第二個參數表示是一個選擇器,因此用這樣一個字符串來表示

總體數據結構

WX20181211-172050@2x.png
相關文章
相關標籤/搜索