談Runtime機制和使用的整體化梳理

發表於2016-07-29

相比“凌波微步”的swift,Object-C被譽為“如來神掌”。傳說Runtime就是支援這“如來神掌”說法的最好體現。聽起來總是這麼的神祕高階,於是總能在各個論壇看到碎片資料,時間一長總記不住哪裡是哪裡,每次都要開啟好幾個網頁。這種記不住象現顯然是知識體系還不完整重要體現。還是自己從Runtime的思想到動手程式碼呈現上做出總結尚為上策。

111252638-2fd0645c206122a9
學習流程圖

一.基本概念

  1. RunTime簡稱執行時,就是系統在執行的時候的一些機制,其中最主要的是訊息機制。
  2. 對於C語言,函式的呼叫在編譯的時候會決定呼叫哪個函式,編譯完成之後直接順序執行,無任何二義性。
  3. OC的函式呼叫成為訊息傳送。屬於動態呼叫過程。在編譯的時候並不能決定真正呼叫哪個函式(事實證明,在編 譯階段,OC可以呼叫任何函式,即使這個函式並未實現,只要申明過就不會報錯。而C語言在編譯階段就會報錯)。
  4. 只有在真正執行的時候才會根據函式的名稱找 到對應的函式來呼叫。

官網文件還提供關於傳統和現代版本Runtime的說明

  1. In the legacy runtime, if you change the layout of instance variables in a class, you must recompile classes that inherit from it.
  2. In the modern runtime, if you change the layout of instance variables in a class, you do not have to recompile classes that inherit from it.
    In addition, the modern runtime supports instance variable synthesis for declared properties (see Declared Properties in The Objective-C Programming Language).

二.知曉OC的方法呼叫在Runtime中具體的實現

1.OC程式碼呼叫一個方法

2.在編譯時RunTime會將上述程式碼轉化成[傳送訊息]

三.常見的作用

既然是“如來神掌”,簡直可以無法無天啦,當街攔下一個人問道“這是馬還是鹿啊?”,那人看是Runtime大人懼怕道“Runtime大人,您說是馬就是馬,是鹿就是鹿~”。Runtime大快“wow哈哈哈~,見你乖巧,我也不為難於你。你缺頭驢是吧?,本大人現在造一頭送於你,遷回家便是!喔~哈哈哈”。

呵呵,扯遠了,回到Runtime作用上。無所不能的事情就不一一介紹了,梳理下較為可能用的幾個地方:

1. 動態的新增物件的成員變數和方法
2. 動態交換兩個方法的實現
3. 實現分類也可以新增屬性
4. 實現NSCoding的自動歸檔和解檔
5. 實現字典轉模型的自動轉換

四.編寫程式碼實現

1. 動態變數控制

1)Sense:

在程式當中,假設XiaoMing的name原來的值為XiaoMing,後來被Runtime偷換了一個名字叫Minggo。那麼,Runtime是如何做到的呢?

2)Step:

①動態獲取XiaoMing類中的所有屬性[當然包括私有]

②遍歷屬性找到對應name欄位

③修改對應的欄位值成Minggo

3)Show Code:

2. 動態交換方法

1)Sense:

在程式當中,假設XiaoMing的第一次回答為firstSay,後來被Runtime交換了一個名字叫secondSay的方法,最終再呼叫firstSay的時候,其實是呼叫了secondSay的實現。那麼,Runtime是如何做到的呢?

2)Step:

①動態找到firstSay和secondSay方法

②交換兩個方法

3)Show Code:

3. 動態新增方法

1)Sense:

在程式當中,假設XiaoMing的中沒有guess這個方法,後來被Runtime新增一個名字叫guess的方法,最終再呼叫guess方法做出相應。那麼,Runtime是如何做到的呢?

2)Step:

①動態給XiaoMing類中新增guess方法:

這裡引數地方說明一下:
(IMP)guessAnswer 意思是guessAnswer的地址指標;
“v@:” 意思是,v代表無返回值void,如果是i則代表int;@代表 id sel; : 代表 SEL _cmd;
“v@:@@” 意思是,兩個引數的沒有返回值。

②呼叫guess方法響應事件:

③編寫guessAnswer的實現:

這個有兩個地方留意一下:
1.void的前面沒有+、-號,因為只是C的程式碼。
2.必須有兩個指定引數(id self,SEL _cmd)

3)Show Code:

4. 動態為Category擴充套件加屬性

這一點上有兩點要表達一下:第一,XCode執行你在Category的.h檔案申明@Property,編譯通過,但執行時如果沒有Runtime處理,進行賦值取值,就馬上報錯。第二,這一點是iOS面試當中經常面到的問題:如何給擴充套件新增屬性?。

1)Sense:

在程式當中,假設XiaoMing的中沒有chineseName這個屬性,後來被Runtime新增一個名字叫chineseName的屬性。那麼,Runtime是如何做到的呢?

2)Step:

①申明chineseName屬性

②動態新增屬性和實現方法

③使用chineseName屬性

3)Show Code:

上邊就是最要的Code了。以下更精彩。

五.效果圖更直觀

 談Runtime機制和使用的整體化梳理

六.原始碼下載地址更詳細

https://github.com/minggo620/iOSRuntimeLearn.git

【原創出品 未經授權 禁止轉載】
【歡迎微友分享轉發 禁止公號等未經授權的轉載】

1252638-032d9c5db0a140c4
微信公眾號:minggo_dev

相關文章