底層14:LLVM、Runtime API

面試題:什么是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。如下:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容