iOS Runtime基礎結構

2021-10-04 05:27:14 字數 2374 閱讀 2934

runtime概念:

oc是基於c的,區別於c的一點就是oc屬於動態語言,並且有物件導向的特性。相比於c,函式的呼叫在編譯的時候會決定呼叫哪個函式。oc會在編譯和鏈結時做的事情放到了執行時(runtime)來處理,其呼叫函式的方法為msg_send,屬於動態呼叫,只有在真正執行才會根據函式名稱找到對應的函式來呼叫。即使呼叫未實現的方法在編譯階段也不會報錯(呼叫階段如果不處理仍會crash),而c語言呼叫未實現的函式在編譯階段就會報錯。

runtime常用使用場景:

動態新增類的屬性以及方法

方法交換

獲取類的屬性

字典轉模型

等等資料結構:

對於isa:

指向他的類物件

root class (class)其實就是 nsobject,nsobject 是沒有超類的,所以 root class(class)的 superclass 指向 nil。

每個 class 都有乙個 isa 指標指向唯一的 meta class

root class(meta)的 superclass 指向 root class(class),也就是 nsobject,形成乙個迴路。

每個 meta class 的 isa 指標都指向 root class (meta)。

為什麼要有元類:

因為類方法是儲存在元類中的,那麼可不可以把元類乾掉,在類中把例項方法和類方法存在兩個不同的陣列中?

答:行是肯定可行的,但是在lookupimporforward執行的時候就得標註上傳入的cls到底是例項物件還是類物件,這也就意味著在查詢方法的快取時同樣也需要判斷cls到底是個啥。

倘若該類存在同名的類方法和例項方法是該呼叫哪個方法呢?這也就意味著還得給傳入的方法帶上是類方法還是例項方法的標識,sel並沒有帶上當前方法的型別(例項方法還是類方法),引數又多加乙個,而我們現在的objc_msgsend()只接收了(id self, sel _cmd, …)這三種引數,第乙個self就是訊息的接收者,第二個就是方法,後續的…就是各式各樣的引數。

通過元類就可以巧妙的解決上述的問題,讓各類各司其職,例項物件就幹儲存屬性值的事,類物件儲存例項方法列表,元類物件儲存類方法列表,完美的符合6大設計原則中的單一職責,而且忽略了對物件型別的判斷和方法型別的判斷可以大大的提公升訊息傳送的效率,並且在不同種類的方法走的都是同一套流程,在之後的維護上也大大節約了成本。

元類的存在巧妙的簡化了例項方法和類方法的呼叫流程,大大提公升了訊息傳送的效率

對於cache_t:

用雜湊表來快取呼叫過的方法,可以提高訪問方法的速度

增量擴充套件來提高容量

對於cache_t中的bucket_t:

兩個成員變數key ,imp

對於class_data_bits_t:

其中包括乙個指向常量的指標 ro,其中儲存了當前類在編譯期就已經確定的屬性、方法以及遵循的協議

objc 類中的屬性、方法還有遵循的協議等資訊都儲存在 class_rw_t 中.

類在記憶體中的位置是編譯期就確定的,類定義的例項方法,會被新增到class_ro_t 的basemethodlist

細看兩個結構體的成員變數會發現很多相同的地方,他們都存放著當前類的屬性、例項變數、方法、協議等等。區別在於:class_ro_t存放的是編譯期間就確定的;而class_rw_t是在runtime時才確定,它會先將class_ro_t的內容拷貝過去,然後再將當前類的分類的這些屬性、方法等拷貝到其中。所以可以說class_rw_t是class_ro_t的超集,當然實際訪問類的方法、屬性等也都是訪問的class_rw_t中的內容。

整體資料結構圖:

runtime訊息機制

IOS runtime簡單使用

一 runtime簡介 runtime簡稱執行時。oc就是執行時機制,也就是在執行時候的一些機制,其中最主要的是訊息機制。對於c語言,函式的呼叫在編譯的時候會決定呼叫哪個函式。對於oc的函式,屬於動態呼叫過程,在編譯的時候並不能決定真正呼叫哪個函式,只有在真正執行的時候才會根據函式的名稱找到對應的函...

iOS runtime,訊息傳送

objective c runtime ios執行時 runtime 詳解 demo ios 訊息傳送與 詳解 ios runtime 的使用場景 實戰篇 method swizzling oc 實現 ios runtime實戰應用 method swizzling method swizzling...

iOS Runtime字型適配

你還在為適配字型大小發愁?看這裡 define myuiscreen 375 ui設計原型圖的手機尺寸寬度 6 6p的 414 implementation uifont runtime void load uifont adapterfontofsize cgfloat fontsize 正常呼叫...