面試題:什么是Runtime,平時(shí)項(xiàng)目中有用到嗎?
OC是一門動(dòng)態(tài)性比較強(qiáng)的編程語(yǔ)言,允許很多操作推遲到程序運(yùn)行時(shí)再進(jìn)行;
OC的動(dòng)態(tài)性就是由Runtime來(lái)支持的和實(shí)現(xiàn)的,Runtime是一套C語(yǔ)言的API,封裝了很多動(dòng)態(tài)性相關(guān)的函數(shù);
平時(shí)編寫的OC代碼,底層都是轉(zhuǎn)化成了Runtime API進(jìn)行調(diào)用;
具體應(yīng)用:
利用關(guān)聯(lián)對(duì)象(AccociatedObject)給分類添加屬性;
遍歷類的所有成員變量(修改textfield的占位文字顏色,字典轉(zhuǎn)模型、自動(dòng)歸檔解檔);
交換方法實(shí)現(xiàn)(交換系統(tǒng)的方法);
利用消息轉(zhuǎn)發(fā)機(jī)制解決方法找不到的異常問(wèn)題;
......
Runtime的使用
1.可以查看它的私有成員變量:
eg:設(shè)置UITextField占位顏色 self.textField.placeholder = @"請(qǐng)輸入名字";
self.textField setValue:[UIColor redColor]forKeyPath:@"_placeholderLable.textColor"];
2.字典轉(zhuǎn)模型:利用Runtime遍歷所有的屬性或者成員變量
3.利用KVC賦值
4.替換方法的實(shí)現(xiàn):class_replaceMethod、method_exchangeImplementations

LLVM -> 中間代碼(.ll) -> 匯編 -> 機(jī)器代碼
中間代碼(IR):
Objective-C在變成機(jī)器代碼之前,會(huì)被LLVM編譯器轉(zhuǎn)換為中間代碼(Intermediate Represention)
可以使用以下命令行指令生成中間代碼:clang -emit -llvm -S main.m
語(yǔ)法簡(jiǎn)介:

具體參考官方文檔:https://llvm.org/docs/LangRef.html
Runtime API
動(dòng)態(tài)創(chuàng)建一個(gè)類(參數(shù):父類, 類名,額外的內(nèi)存空間)
Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes);
注冊(cè)一個(gè)類(要在類注冊(cè)之前添加成員變量):void objc_registerClassPair(Class cls);
銷毀一個(gè)類:void objc_disposeClassPair(Class cls);
獲取isa指向的Class:Class object_getClass(id obj);
設(shè)置isa指向的Class:Class object_setClass(id obj, Class cls);
判斷一個(gè)OC對(duì)象是否為Class:BOOL object_isClass(id obj);
判斷一個(gè)Class是否為元類:BOOL class_inMetaClass(Class cls);
獲取父類:Class class_getSuperclass(Class cls);
獲取一個(gè)實(shí)例變量:Ivar class_getInstanceVariable(Class cls, const char *name);
拷貝實(shí)例變量列表(最后需要調(diào)用free釋放):Ivar *class_copyIvarList(Class cls, unsigned int *outCount)
設(shè)置和獲取成員變量的值:
void object_setIvar(id obj, Ivar ivar, id value);?
id object_getIvar(id obj, Ivar ivar)
動(dòng)態(tài)添加成員變量(已經(jīng)注冊(cè)的類是不能動(dòng)態(tài)添加成員變量的)
BOOL class_addIvar(Class cls, const char *name, size_t size, uint8_t alignment, const char *types);
獲取成員變量的相關(guān)信息
const char *ivar_getName(Ivar v);
const char *ivar_getTypeEncoding(Ivar v);


下面是一個(gè)利用runtimeAPI的可以實(shí)現(xiàn)監(jiān)控項(xiàng)目中所有點(diǎn)擊事件的實(shí)現(xiàn)方法

當(dāng)然load方法雖然一般情況下只調(diào)用一次,但是某些特殊情況的調(diào)用為了保險(xiǎn)起見還是加上一個(gè)dispatch_once。如下:
