iOS高階底層原理 runtime

2021-10-08 06:22:30 字數 1874 閱讀 5258

runtime 是ios的執行時,用於實現ios載入和呼叫屬性和方法。

函式中load方法沒有使用runtime機制,是底層直接呼叫的函式。load執行順序是由編譯時的檔案順序相同,先編譯的先執行load,類優先於分類的順序呼叫+load方法。

initialize

+initialize方法是在類或類的子類收到第一條訊息之前被呼叫的,這裡所指的訊息包括例項方法和類方法的呼叫。

也就是說+initialize方法是以懶載入的方式被呼叫的,如果一直沒有給乙個類或他的子類傳送訊息,那麼這個類的+initialize方法是永遠不會呼叫的。

當我們向某個類傳送訊息時,runtime會呼叫imp lookupimporforward(...)這個函式在類中查詢相應方法的實現或進行訊息**,開啟objc-runtime-new.h找到這個函式:

imp lookupimporforward

(class cls, sel sel, id inst,

bool initialize, bool cache, bool resolver)..

.}

從中可以看到當類沒有初始化時,會呼叫_class_initialize(class cls)對類進行初始化:

void

_class_initialize

(class cls)..

....

if(reallyinitialize)

// 傳送呼叫類方法initialize的訊息((

void(*

)(class, sel)

)objc_msgsend)

(cls, sel_initialize);.

....

.}

在這裡,先是對入參的父類進行遞迴呼叫,以確保父類優先於子類初始化。

+initialize方法在runtime中是以傳送訊息的方式呼叫的,所以子類會覆蓋父類的實現,分類會覆蓋類的實現,多個分類只會呼叫乙個分類的+initialize方法。

分類通過runtime動態將分類的屬性和方法合併到類物件,元類物件中。

#import "classname + categoryname.h"

#import static void *strkey = &strkey;

@implementation classname (categoryname)

-(void)setstr:(nsstring *)str

-(nsstring *)str

method swizzling

每個類都維護乙個方法(method)列表,method則包含sel和其對應imp的資訊,方法交換做的事情就是把sel和imp的對應關係斷開,並和新的imp生成對應關係。

交換前:asel->aimp bsel->bimp

交換後:asel->bimp bsel->aimp

方法交換之後,「方法的實現」 變成了 「你的處理**」 + 「方法的實現」

+ (void)swizzlemethods:(class)class originalselector:(sel)origsel swizzledselector:(sel)swizsel  else 

}

呼叫過程,涉及到了isa指標

isa

ps:mask 掩碼,一般用來進行按位(與&)運算。

iOS 類的底層原理

首先我們探索來例項物件 類物件 元類之間的關係,執行下面 可以看到class1 class2 class3列印結果一樣,我們是不是可以認為類物件只有乙個,元類是乙個虛擬的類由系統幫我們建立,是類物件所屬的類,而元類歸屬是根元類,根元類的歸屬是自身。例項物件 person p person alloc...

iOS 底層原理之 Block

block 本質上也是乙個 oc 物件,它內部也有個 isa 指標 block 是封裝了函式呼叫以及函式呼叫環境的 oc 物件 block 的底層結構如下圖所示 原始碼解析 struct gsblock load block impl 0 block impl struct block impl g...

iOS底層原理總結 OC方法的本質

int main int argc,const char argv return 0 可以看出在我們進行lgperson初始化的時候,我們都知道會呼叫alloc,init.我這裡為了簡單只呼叫 new 但是底層不是像我們利用呼叫的,而是呼叫了乙個函式objc msgsend這就是我們訊息傳送的方法,...