Runtime 10種用法(沒有比這更全的了)
閱讀了多篇執行時的文章,感覺都很不錯,從幾篇文章裡面提取一些個人認為比較重要的,偏實戰的知識點的摘錄,另外還結合了個人的創造形成此文。再牛逼的技術和實戰結合才有意義,本篇介紹技術儘量和實戰聯絡起來,有些沒講明白的,我給的連結裡面都有,所以我就不贅述了,如果覺得可以就點個贊吧,哈哈。不需要打賞。
1)替換系統方法,
2)字典轉model,
3)歸檔,
4)萬能控制器跳轉
四個偏實戰的方法從不同的文章中聚合到這裡.沒講明白的麻煩看客去我給的連結裡面看看,他們都講了
對文章的內容我用一張圖介紹吧(圖只管明瞭,我喜歡,大家也喜歡)
runtime 文章收集:
如下4篇內容有相似的 小白都可以看懂runtime,值得細看
先用一張圖對文章做一個介紹吧 (圖只管,易懂方便回憶,我喜歡,大家也喜歡)
what(runtime 是什麼)
Runtime基本是用C和彙編寫的,可見蘋果為了動態系統的高效而作出的努力。你可以在這裡下到蘋果維護的開原始碼。蘋果和GNU各自維護一個開源的runtime版本,這兩個版本之間都在努力的保持一致。Objective-C 從三種不同的層級上與 Runtime 系統進行互動,分別是通過 Objective-C 原始碼,通過 Foundation 框架的NSObject類定義的方法,通過對 runtime 函式的直接呼叫。大部分情況下你就只管寫你的Objc程式碼就行,runtime 系統自動在幕後辛勤勞作著。
RunTime簡稱執行時,就是系統在執行的時候的一些機制,其中最主要的是訊息機制。
對於C語言,函式的呼叫在編譯的時候會決定呼叫哪個函式,編譯完成之後直接順序執行,無任何二義性。
OC的函式呼叫成為訊息傳送。屬於動態呼叫過程。在編譯的時候並不能決定真正呼叫哪個函式(事實證明,在編 譯階段,OC可以呼叫任何函式,即使這個函式並未實現,只要申明過就不會報錯。而C語言在編譯階段就會報錯)。
只有在真正執行的時候才會根據函式的名稱找 到對應的函式來呼叫。
where(哪些地方使用runtime)
1.將某些OC程式碼轉為執行時程式碼,探究底層,比如block的實現原理(上邊已講到);
需求:比如iOS6 升級 iOS7 後需要版本適配,根據不同系統使用不同樣式圖片(擬物化和扁平化),如何通過不去手動一個個修改每個UIImage的imageNamed:方法就可以實現為該方法中加入版本判斷語句?
步驟:
a、為UIImage建一個分類(UIImage+Category)
b、在分類中實現一個自定義方法,方法中寫要在系統方法中加入的語句,比如版本判斷[參考 ]
+ (UIImage*)xh_imageNamed:(NSString*)name {
doubleversion = [[UIDevicecurrentDevice].systemVersiondoubleValue];
if(version >=7.0) {
// 如果系統版本是7.0以上,使用另外一套檔名結尾是‘_os7’的扁平化圖片
name = [name stringByAppendingString:@"_os7"]; }
return[UIImagexh_imageNamed:name];
}
c、分類中重寫UIImage的load方法,實現方法的交換(只要能讓其執行一次方法交換語句,load再合適不過了)
+ (void)load {
// 獲取兩個類的類方法
Method m1 = class_getClassMethod([UIImageclass],@selector(imageNamed:));
Method m2 = class_getClassMethod([UIImageclass],@selector(xh_imageNamed:));
// 開始交換方法實現
method_exchangeImplementations(m1, m2);
}
注意:自定義方法中最後一定要再呼叫一下系統的方法,讓其有載入圖片的功能,但是由於方法交換,系統的方法名已經變成了我們自定義的方法名(有點繞,就是用我們的名字能呼叫系統的方法,用系統的名字能呼叫我們的方法),這就實現了系統方法的攔截!
利用以上思路,我們還可以給 NSObject 新增分類,統計建立了多少個物件,給控制器新增分類,統計有建立了多少個控制器,特別是公司需求總變的時候,在一些原有控制元件或模組上新增一個功能,建議使用該方法!
3.實現分類也可以增加屬性;
4.實現NSCoding的自動歸檔和自動解檔;(不用對每個屬性edcode和decode了,如果幾十個屬性一個個的encode和decode真的很麻煩啊,使用執行時可以遍歷出每個物件的屬性,陣列的方式遍歷eccode,decode)
用執行時的歸檔方法
不用執行時的歸檔方法:(還好只有5個屬性,如果20個,30個或者後臺突然增加了屬性,這麼直接寫死估計程式碼就不靈了)
5.實現字典和模型的自動轉換(核心就是可以遍歷出字典中的每個屬性,json解析中大牛框架都用了這個特性,包括MJEXtension,YYModel,jsonModel都是將json轉換為字典,再遍歷字典中的每個屬性來進行modle的轉換)。
MJextension 使用執行時轉換的json轉model的部分程式碼摘錄
YYModel json轉model 核心程式碼 摘錄
JsonModel json字典轉model 摘錄
獲取屬性的列表的方法是字典轉模型的比較核心的方法,
OBJC_EXPORT Ivar *class_copyIvarList(Class cls, unsigned int *outCount)
__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
致此可以下個結論嗎?
基本上主流的json 轉model 都少不了,使用執行時動態獲取屬性的屬性名的方法,來進行字典轉模型替換,字典轉模型效率最高的(耗時最短的)的是KVC,其他的字典轉模型是在KVC 的key 和Value 做處理,動態的獲取json 中的key 和value ,當然轉換的過程中,第三方框架需要做一些判空啊,鑲嵌的邏輯處理, 再進行KVC 轉模型.這句程式碼 [xx setValue:value forKey:key];無論JsonModle,YYKIt,MJextension 都少不了[xx setValue:value forKey:key];這句程式碼的,不信可以去搜,這是字典轉模型的核心方法,
6)動態增加方法 (動態的為某個類或物件增加一個方法,摘錄文章中有詳細介紹)
7)動態變數控制 (動態對某個物件的變數的值進行替換,摘錄文章有詳細介紹)
8)實現萬能控制器跳轉
產品來一變態需求,推送過來的訊息,要跳轉到任意控制器.利用runtime動態生成物件、屬性、方法這特性,我們可以先跟服務端商量好,定義跳轉規則,比如要跳轉到A控制器,需要傳屬性id、type,那麼服務端返回字典給我,裡面有控制器名,兩個屬性名跟屬性值,客戶端就可以根據控制器名生成物件,再用kvc給物件賦值,這樣就搞定了
9)外掛開發
外掛入門
XCode 有個很坑爹的地方,就是它並不官方支援外掛開發,官方沒有文件,XCode 也沒有開源,但由於 XCode 是 Objective-C 寫的,OC 動態性太強大,導致在這麼封閉的情況下民間還是可以做出各種外掛,其核心開發方式就是:
dump 出 Xcode 所有標頭檔案,知道 Xcode 裡有哪些類和介面。
通過標頭檔案方法名猜測方法的作用,swizzle 這些方法,插入自己的程式碼實現外掛邏輯。
通過 NSNotificationCenter 監聽各種事件的發生。
更詳細的開發教程網上有不少文章,有興趣的自行搜尋吧。
10)Jspath 熱更新 也是使用執行時,jspatch 基本上算是黑科技,線上修復版本bug,微信都使用了這個技術,詳情百度“JSPatch”,此處省略30000字
文/hjl_wg(簡書作者)
原文連結:http://www.jianshu.com/p/3182646001d1
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。