runtime簡介:
Runtime 又叫運行時,是一套底層的 C 語言 API,其為 iOS 內部的核心之一,我們平時編寫的 OC 代碼,底層都是基于它來實現(xiàn)的。
人在江湖飄,身不由己啊。循環(huán)不停的業(yè)務,都幾乎沒有時間去總結。就是會用一些,但是真正想下runtime這個。自己還真說不出個所以然來。
爬爬帖子,給自己留個印兒。
OC最實用的runtime總結,面試、工作你看我就足夠了!
讓你快速上手Runtime
runtime詳解
詳解runtime運行時機制
萬能控制器跳轉
看一張圖:

十大用法:
- 1.將某些OC代碼轉為運行時代碼,探究底層,比如block的實現(xiàn)原理
- 2.攔截系統(tǒng)自帶的方法調用(Swizzle 黑魔法),也可以說成對系統(tǒng)的方法進行替換,比如攔截imageNamed:、viewDidLoad、alloc
- 3.實現(xiàn)分類也可以增加屬性;
- 4.實現(xiàn)NSCoding的自動歸檔和自動解檔;(不用對每個屬性edcode和decode了,如果幾十個屬性一個個的encode和decode真的很麻煩啊,使用運行時可以遍歷出每個對象的屬性,數(shù)組的方式遍歷eccode,decode)
- 5.實現(xiàn)字典和模型的自動轉換(核心就是可以遍歷出字典中的每個屬性,json解析中大??蚣芏加昧诉@個特性,包括MJEXtension,YYModel,jsonModel都是將json轉換為字典,再遍歷字典中的每個屬性來進行modle的轉換)。
- 6.動態(tài)增加方法 (動態(tài)的為某個類或對象增加一個方法,摘錄文章中有詳細介紹)
- 7.動態(tài)變量控制 (動態(tài)對某個對象的變量的值進行替換,摘錄文章有詳細介紹)
- 8.實現(xiàn)萬能控制器跳轉
產品來一變態(tài)需求,推送過來的消息,要跳轉到任意控制器.利用runtime動態(tài)生成對象、屬性、方法這特性,我們可以先跟服務端商量好,定義跳轉規(guī)則,比如要跳轉到A控制器,需要傳屬性id、type,那么服務端返回字典給我,里面有控制器名,兩個屬性名跟屬性值,客戶端就可以根據(jù)控制器名生成對象,再用kvc給對象賦值,這樣就搞定了。
組件化其實也用到了runtime,根據(jù)url,動態(tài)獲取到類,參數(shù)等??梢詤⒖寄⒐浇珠_源項目
- 9.插件開發(fā)
- 10.Jspath 熱更新 也是使用運行時,jspatch 基本上算是黑科技,在線修復版本bug,雖然被蘋果爸爸禁止使用了一段時間,后來好像談妥了,又可以付費使用了。
總結:
綜上所述,runtime核心用法有一下三點。
Method class_getClassMethod(Class cls , SEL name) //獲得某個類的類方法
Method class_getInstanceMethod(Class cls , SEL name) // 獲得某個類的實例對象方法
void method_exchangeImplementations(Method m1 , Method m2) // 交換兩個方法的實現(xiàn)
1、方法簡單的交換
下面通過runtime 實現(xiàn)方法交換,類方法用class_getClassMethod ,對象方法用class_getInstanceMethod
// 獲取兩個類的類方法
Method m1 = class_getClassMethod([Person class], @selector(run));
Method m2 = class_getClassMethod([Person class], @selector(study));
// 開始交換方法實現(xiàn)
method_exchangeImplementations(m1, m2);
// 交換后,先打印學習,再打印跑!
[Person run];
[Person study];
2、攔截系統(tǒng)方法
步驟:
1、為UIImage建一個分類(UIImage+Category)
2、在分類中實現(xiàn)一個自定義方法,方法中寫要在系統(tǒng)方法中加入的語句,比如版本判斷
+ (UIImage *)xh_imageNamed:(NSString *)name {
double version = [[UIDevice currentDevice].systemVersion doubleValue];
if (version >= 7.0) {
// 如果系統(tǒng)版本是7.0以上,使用另外一套文件名結尾是‘_os7’的扁平化圖片
name = [name stringByAppendingString:@"_os7"];
}
return [UIImage xh_imageNamed:name];
}
3、分類中重寫UIImage的load方法,實現(xiàn)方法的交換(只要能讓其執(zhí)行一次方法交換語句,load再合適不過了)
+ (void)load {
// 獲取兩個類的類方法
Method m1 = class_getClassMethod([UIImage class], @selector(imageNamed:));
Method m2 = class_getClassMethod([UIImage class], @selector(xh_imageNamed:));
// 開始交換方法實現(xiàn)
method_exchangeImplementations(m1, m2);
}
注意:自定義方法中最后一定要再調用一下系統(tǒng)的方法,讓其有加載圖片的功能,但是由于方法交換,系統(tǒng)的方法名已經變成了我們自定義的方法名(有點繞,就是用我們的名字能調用系統(tǒng)的方法,用系統(tǒng)的名字能調用我們的方法),這就實現(xiàn)了系統(tǒng)方法的攔截!
3、獲得一個類的所有成員變量
Ivar *class_copyIvarList(Class cls , unsigned int *outCount) //獲得一個類的所有成員變量
const char *ivar_getName(Ivar v) //獲得成員變量的名字
const char *ivar_getTypeEndcoding(Ivar v) //獲得成員變量的類型
//獲取Person類中所有成員變量的名字和類型
unsigned int outCount = 0;
Ivar *ivars = class_copyIvarList([Person class], &outCount);
// 遍歷所有成員變量
for (int i = 0; i < outCount; i++) {
// 取出i位置對應的成員變量
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
const char *type = ivar_getTypeEncoding(ivar);
NSLog(@"成員變量名:%s 成員變量類型:%s",name,type);
}
// 注意釋放內存!
free(ivars);
參考文章:
https://blog.csdn.net/qq_30513483/article/details/51312848