Runtime的個人理解

剛接觸runtime的時候,就感覺很陌生,完全沒有見過相關(guān)代碼归榕。所以趁著閑時間看了看官方解釋以及網(wǎng)上各種大佬的詳細分析,用自己的大白話總結(jié)一下吱涉,不足之處還希望各位大佬們指點一下刹泄,共同進步嘛!

1. Runtime是什么怎爵。

在這里先放上runtime的源碼和runtime官方api:

*源碼:objc-runtime

*官方API:Objective-C Runtime

Objective-C 擴展了 C 語言循签,并加入了面向?qū)ο筇匦院?Smalltalk 式的消息傳遞機制。而這個擴展的核心是一個用 C 和 編譯語言 寫的 Runtime 庫疙咸。它是 Objective-C 面向?qū)ο蠛蛣討B(tài)機制的基石。Objective-C 是一個動態(tài)語言风科,這意味著它不僅需要一個編譯器撒轮,也需要一個運行時系統(tǒng)來動態(tài)得創(chuàng)建類和對象乞旦、進行消息傳遞和轉(zhuǎn)發(fā)。理解 Objective-C 的 Runtime 機制可以幫我們更好的了解這個語言题山,適當?shù)臅r候還能對語言進行擴展兰粉,從系統(tǒng)層面解決項目中的一些設計或技術(shù)問題。了解 Runtime 顶瞳,要先了解它的核心 - 消息傳遞 (Messaging)玖姑。

對于從事iOS開發(fā)的人來說,面試差不多都會問慨菱。所有人都會回答【Runtime是運行時】焰络,但是再往下具體的有深度的對于我來說就只能說個皮毛了。無非就是字典轉(zhuǎn)模型符喝,歸檔/解檔闪彼,給分類動態(tài)添加屬性,交換方法协饲。畏腕。。廢話就到這了茉稠!回到正題描馅。


由上面一長段話可以得出,Runtime的核心就是消息傳遞而线。

下面來看看所謂的運行時都干了什么铭污!

一個對象的方法例如這樣[obj doSomething],到了編譯器轉(zhuǎn)成消息發(fā)送objc_msgSend(obj, @selector(doSomething));如果帶參數(shù)的話吞获,如:[obj doSomething:(id)arg...];到了編譯器轉(zhuǎn)成消息發(fā)送objc_msgSend(obj, selector, arg1, arg2, ...);

objc_msgSend就是消息傳遞况凉。在了解objc_msgSend之前,必須要知道以下兩點:


1.1 類的定義

struct objc_class {

    Class isa  OBJC_ISA_AVAILABILITY;

    //isa指針. 對象的指針—>類各拷,類的指針—>元類刁绒,元類—>根元類—>自己 形成閉環(huán);

    #if !__OBJC2__

    Class super_class;//父類

    const char *name;//類名

    long version;//類的版本信息烤黍,默認為0

    long info;//類信息知市,供運行期使用的一些位標識

    long instance_size;//類的實例變量大小

    struct objc_ivar_list *ivars;// 類的成員變量鏈表

    struct objc_method_list **methodLists;// 方法鏈表

    struct objc_cache *cache;//方法緩存

    struct objc_protocol_list *protocols;//協(xié)議鏈表#

    endif

}OBJC2_UNAVAILABLE;

1.2 objc_method_list里面有什么?

typedef struct objc_method * Method;

struct objc_method

{

    SEL method_name;//方法名稱

    charchar * method_typesE;//參數(shù)和返回類型的描述

    IMP method_imp;//方法具體實現(xiàn)的指針速蕊,指向?qū)膶崿F(xiàn)代碼

}

SEL:

從SEL類型的成員為method_name可以知道嫂丙,SEL大概代表一個方法的名字,作用是標記方法區(qū)分方法

IMP:

IMP是一個函數(shù)指針规哲,指向objc_method對應方法的實現(xiàn)部分跟啤。


下面我們就說說Runtime的核心objc_msgSend消息傳遞。

2 消息傳遞的流程

1.objc_msgSend()函數(shù)會根據(jù)調(diào)用的對象isa指針找到所屬的class中的objc_method_list。然后從上向下遍歷隅肥,根據(jù)SEL的方法名稱竿奏,找到IMP指針跳轉(zhuǎn)到方法的實現(xiàn)代碼,調(diào)用這個方法的實現(xiàn)腥放。

2.如果找不到泛啸,會根據(jù)所屬類的superClass指針,沿著類的繼承體系繼續(xù)向上查找(向父類查找)秃症,如果 能找到與名稱相符的方法候址,就根據(jù)IMP指針跳轉(zhuǎn)到方法的實現(xiàn)代碼,調(diào)用這個方法的實現(xiàn)种柑。

3.如果在繼承體系中還是找不到相符的方法岗仑,此時就會執(zhí)行”消息轉(zhuǎn)發(fā)(message forwarding)“操作。


3 消息轉(zhuǎn)發(fā)機制

消息轉(zhuǎn)發(fā)機制包括三類:1.類的動態(tài)方法解析2.備用接受者對象3.完整的消息轉(zhuǎn)發(fā)

1.類的動態(tài)方法解析:征詢消息接受者所屬的類莹规,看其是否能動態(tài)添加方法赔蒲,以處理當前“這個未知的選擇子(unknown selector)。

實例對象在接受到無法解讀的消息后良漱,首先會調(diào)用其所屬類的下列類方法:

+ (BOOL)resolveInstanceMethod:(SEL)selector

類對象在接受到無法解讀的消息后舞虱,那么運行期系統(tǒng)就會調(diào)用另外的一個方法:

+ (BOOL)resolveClassMethod:(SEL)selector

如果運行期系統(tǒng)已經(jīng)執(zhí)行完了動態(tài)方法解析,那么消息接受者自己就無法再以動態(tài)新增方法的形式來響應包含該未知選擇子的消息了母市,此時就進入了第二階段——完整的消息轉(zhuǎn)發(fā)矾兜。運行期系統(tǒng)會請求消息接受者以其他手段來處理與消息相關(guān)的方法調(diào)用。

2.備用接受者對象(replacement receiver)

當前接受者如果不能處理這條消息患久,運行期系統(tǒng)會請求當前接受者讓其他接受者處理這條消息椅寺,與之對應的方法是:

- (id)forwardingTargetForSelector:(SEL)selector

方法參數(shù)代表未知的選擇子,返回值為備援接受者蒋失,若當前接受者能找到備援接受者返帕,就直接返回,這個未知的選擇子將會交由備援接受者處理篙挽。如果找不到備援接受者荆萤,就返回nil,此時就會啟用”完整的消息轉(zhuǎn)發(fā)機制“铣卡。

3.完整的消息轉(zhuǎn)發(fā)

如果轉(zhuǎn)發(fā)算法已經(jīng)來到了這一步链韭,那么代表之前的所有轉(zhuǎn)發(fā)嘗試都失敗了,此時只能啟用完整的消息轉(zhuǎn)發(fā)機制煮落。

完整的消息轉(zhuǎn)發(fā)機制是這樣的:首先創(chuàng)建NSInvocation對象敞峭,把尚未處理的那條消息有關(guān)的全部細節(jié)封裝于這個NSInvocation對象中。

此對象中包含選擇子(selector)蝉仇、目標(target)及參數(shù)旋讹。在觸發(fā)NSInvocation對象時殖蚕,”消息派發(fā)系統(tǒng)(message-dispatch system)“將親自觸發(fā),把消息派發(fā)給目標對象骗村。此步驟中會調(diào)用下面這個方法來轉(zhuǎn)發(fā)消息:

- (void)forwardInvocation:(NSInvocation *)invocation

調(diào)用這個方法如果不能處理就會調(diào)用父類的相關(guān)方法嫌褪,一直到NSObject的這個方法,如果NSObject都無法處理就會調(diào)用doesNotRecognizeSelector:方法拋出異常胚股。

以上就是我對Runtime的理解。希望對有緣人有幫助裙秋。如果有不足或錯誤的地方琅拌,還望各位好友指出,共同進步摘刑。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末进宝,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子枷恕,更是在濱河造成了極大的恐慌党晋,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件徐块,死亡現(xiàn)場離奇詭異未玻,居然都是意外死亡,警方通過查閱死者的電腦和手機胡控,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門扳剿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人昼激,你說我怎么就攤上這事庇绽。” “怎么了橙困?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵瞧掺,是天一觀的道長。 經(jīng)常有香客問我凡傅,道長辟狈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任像捶,我火速辦了婚禮上陕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拓春。我一直安慰自己释簿,他們只是感情好,可當我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布硼莽。 她就那樣靜靜地躺著庶溶,像睡著了一般煮纵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上偏螺,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天行疏,我揣著相機與錄音,去河邊找鬼套像。 笑死酿联,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的夺巩。 我是一名探鬼主播贞让,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼柳譬!你這毒婦竟也來了喳张?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤美澳,失蹤者是張志新(化名)和其女友劉穎销部,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體制跟,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡舅桩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了凫岖。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片江咳。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖哥放,靈堂內(nèi)的尸體忽然破棺而出歼指,到底是詐尸還是另有隱情,我是刑警寧澤甥雕,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布踩身,位于F島的核電站,受9級特大地震影響社露,放射性物質(zhì)發(fā)生泄漏挟阻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一峭弟、第九天 我趴在偏房一處隱蔽的房頂上張望附鸽。 院中可真熱鬧,春花似錦瞒瘸、人聲如沸坷备。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽省撑。三九已至赌蔑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間竟秫,已是汗流浹背娃惯。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留肥败,地道東北人趾浅。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像拙吉,于是被迫代替她去往敵國和親潮孽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內(nèi)容