動態(tài)特性:
動態(tài)類型棚愤、動態(tài)綁定、動態(tài)方法決議毛甲、動態(tài)加載、內(nèi)省
編譯器會把[接收器 消息]形式的對象消息具被,轉(zhuǎn)換為含有方法簽名的C函數(shù)調(diào)用語句玻募。如:
OC :
[[Person alloc] init];
runtime :
objc_msgSend(objc_msgSend(“Person” ,“alloc”), “init”)一姿;
為了正確的生成對象消息傳遞代碼七咧,編譯器需要獲得選擇器和方法簽名(method signature)。
同時叮叹,這時候需要確定接收器的類型(動態(tài)類型)艾栋。OC通過id數(shù)據(jù)類型來支持動態(tài)類型。在實(shí)際使用中衬横,往往通過introspection(內(nèi)省)來確定該對象的實(shí)際所屬類型裹粤。
id obj = someInstance;
if ([obj isKindOfClass:someClass]) {
//todo
}
內(nèi)省方法舉例:
isKindOfClass:判斷接收器是目標(biāo)類或者其子類的實(shí)例
someInstanceisMemberOfClass:someClass? ? 判斷someInstance是否是某個類的成員终蒂,和isKindOfClass類似
someInstancerespondsToSelector:@selector(someFunction)? 判斷someInstance是否實(shí)現(xiàn)或者繼承了能夠?qū)χ付ㄏ⒆鞒龌貞?yīng)的方法蜂林。
someInstanceconformsToProtocol:@protocol(someProtocol)? 判斷someInstance是否遵循某協(xié)議
someInstancemethodSignatureForSelector:@selector(someFunction)? 為選擇器提取方
對于源代碼中的類和對象來說遥诉,編譯器會創(chuàng)建數(shù)據(jù)結(jié)構(gòu)(至少包含了一個指向相關(guān)類的isa指針和方法列表)和函數(shù)調(diào)用語句,以動態(tài)的方式將接收器(類/對象)和消息選擇器和方法實(shí)現(xiàn)代碼對應(yīng)起來(動態(tài)綁定)噪叙。動態(tài)綁定實(shí)現(xiàn)了OOP的多態(tài)性矮锈。因?yàn)樵S多接收器(對象)可能會實(shí)現(xiàn)相同的方法,調(diào)用方法的方式會動態(tài)變化睁蕾。下面附上個人感覺很不錯的兩幅圖:
動態(tài)方法決議說明:
使用動態(tài)方法決議可以實(shí)現(xiàn)方法的動態(tài)實(shí)現(xiàn)苞笨。使用Objective-C中的@dynamic指令,可以告知編譯器與屬性關(guān)聯(lián)的方法會以動態(tài)的方式實(shí)現(xiàn)子眶。在OC消息轉(zhuǎn)發(fā)機(jī)制被觸發(fā)之前瀑凝,對應(yīng)的類的+resolveClassMethod:和+resolveInstanceMethod:將會先被調(diào)用,在此時有機(jī)會動態(tài)地向類或者實(shí)例添加新的方法臭杰,也即類的實(shí)現(xiàn)是可以動態(tài)綁定的粤咪。
runtime由編譯器和運(yùn)行時系統(tǒng)庫(C庫)組成。
*在程序運(yùn)行過程中, 動態(tài)創(chuàng)建一個類(比如KVO的底層實(shí)現(xiàn))(objc_allocateClasspair([NSObject , "ClassName" , 0]);)
*在程序運(yùn)行過程中, 動態(tài)地為某個類添加屬性\方法, 修改屬性值\方法
*遍歷一個類的所有成員變量(屬性)\所有方法渴杆。例如:我們需要對一個類的屬性進(jìn)行歸檔解檔的時候?qū)傩蕴貏e的多寥枝,這時候,我們就會寫很多對應(yīng)的代碼磁奖,但是如果使用了runtime就可以動態(tài)設(shè)置囊拜!
常用函數(shù):
objc_allocateClassPair//創(chuàng)建類
objc_registerClassPair//注冊創(chuàng)建的類
objc_getClass//訪問對象的類定義
class_getInstanceMethod//獲取方法
class_getSuperclass
class_getName
class_getVersion
class_getInstanceSize
class_copyIvarList//獲取實(shí)例變量列表
class_copyMethodList//獲取方法列表
class_copyPropertyList//獲取屬性列表
class_copyProtocolList//獲取協(xié)議列表
method_getTypeEncoding//獲取方法簽名
在這里介紹一個最近用到的方法(使用objc_setAssociatedObject給已有類添加了屬性,重寫setter比搭、getter方法)
objc_setAssociatedObject把一個對象與另外一個對象進(jìn)行關(guān)聯(lián)冠跷。該函數(shù)需要四個參數(shù):源對象,關(guān)鍵字(必須是唯一)身诺,關(guān)聯(lián)的對象和一個關(guān)聯(lián)策略蔽莱。
一個objc_setAssociatedObject使用比較好的介紹:鏈接