補(bǔ)一下:runtime使用DEMO
以前對runtime的使用和了解都很模糊。這段時間呻疹,把runtime機(jī)制好好學(xué)習(xí)、整理了一下。
##什么是runtime
runtime是一套比較底層的純C語言API馆蠕,屬于1個C語言庫,包含了很多底層的C語言API惊奇。
##runtime對Objective-C影響
Objective-C之所以是一個動態(tài)語言互躬,可以動態(tài)得創(chuàng)建類和對象、進(jìn)行消息傳遞和轉(zhuǎn)發(fā)颂郎。正因為它擁有`Runtime`這個了不起的庫吼渡。
(ps:靜態(tài)語言:它的數(shù)據(jù)類型是在編譯期間檢查的,編寫時必須申明所有變量的數(shù)據(jù)類型)
##runtime核心—消息傳遞
Objective-C中對象調(diào)用某個方法乓序,它不像靜態(tài)語言寺酪,在編譯時就已經(jīng)決定在某塊內(nèi)存中執(zhí)行函數(shù)方法,而是在運行時給obj對象發(fā)送一條方法消息替劈,runtime會根據(jù)對象能否對這條消息作出響應(yīng)給出不同處理方式寄雀。
因為在編寫Objective-C函數(shù)調(diào)用時,都會被轉(zhuǎn)換成一個C的函數(shù)調(diào)用:`-objc_msgSend()`
```例:
[person work] => objc_msgSend(person, @selector(work))
```
###消息傳遞的執(zhí)行過程
在`runtime.h`頭文件中抬纸,我們可以看出咙俩,OC中的類,對象以及方法其實都是一個C的結(jié)構(gòu)體。
`IMP:即函數(shù)指針阿趁,為方法具體實現(xiàn)代碼塊地址`
下面我們通過一個流程圖來看看`objc_mgSend`傳遞過程中做了什么膜蛔。
以`[obj work]`為例:
####objc_cache作用
流程圖這種執(zhí)行方式效率較低。因為一個class方法列表中的方法脖阵,我們可能常常連一半也用不到皂股,而每個消息都需要遍歷一邊`objc_method_list`這樣消耗很大 。所以我們使用`objc_cache`,在找到 `method` 之后命黔,把 `method_imp` 對應(yīng) `method_name` 利用鍵值存儲起來呜呐。下次再接收到 `method` 消息時,可以直接在 `cache` 中查詢使用悍募。
##runtime之動態(tài)方法解析和消息轉(zhuǎn)發(fā)
####如果流程圖過程中蘑辑,我們最終還是沒有找到`work_imp`,那么我們的程序?qū)⒚媾R崩潰坠宴,這時`runtime` 還給我們提供了動態(tài)添加方法的補(bǔ)救措施洋魂。
-Runtime提供了三種方式來將原來的方法實現(xiàn)代替掉。
####1.`Method Resolution`: 當(dāng) `Runtime` 系統(tǒng)在Cache和方法分發(fā)表中(包括超類)找不到要執(zhí)行的方法時喜鼓,`Runtime`會調(diào)用 `resolveInstanceMethod:`或`resolveClassMethod:`來給程序員一次動態(tài)添加方法實現(xiàn)的機(jī)會副砍。我們需要用`class_addMethod`函數(shù)完成向特定類添加特定方法實現(xiàn)的操作
由于`Method Resolution`不能像消息轉(zhuǎn)發(fā)那樣可以交給其他對象來處理,所以只適用于在原來的類中代替掉庄岖。
```
+ (BOOL)resolveInstanceMethod:(SEL)aSEL
{
if (aSEL == @selector(method)) {
?class_addMethod([self class], @selector(method), (IMP)method, "v@:");
?return YES;
}
?return [super resolveInstanceMethod:aSEL];
}```
####2. `Fast Forwarding`: 它可以將消息處理轉(zhuǎn)發(fā)給其他對象豁翎,使用范圍更廣,不只是限于原來的對象隅忿。
```
- (id)forwardingTargetForSelector:(SEL)aSEL
{
if(aSelector == @selector(method:)){
return alternateObject;
}
return [super forwardingTargetForSelector:aSEL];
}```
如果此方法返回nil或self,則會進(jìn)入消息轉(zhuǎn)發(fā)機(jī)制(forwardInvocation:);否則將向返回的對象重新發(fā)送消息心剥。
####3. `Normal Forwarding`: 它跟Fast Forwarding一樣可以消息轉(zhuǎn)發(fā),但它能通過NSInvocation對象獲取更多消息發(fā)送的信息硼控,例如:target刘陶、selector、arguments和返回值等信息牢撼。
```
- (void)forwardInvocation:(NSInvocation *)anInvocation {
SEL selector = [anInvocation selector];
newClass *Obj = [newClass new];
if ([mobile respondsToSelector:selector]) {
[anInvocation invokeWithTarget:Obj];
}
}```
##runtime的一些使用?
-獲取類的屬性列表
-獲取類的方法列表
-獲取類的協(xié)議列表
-獲取類的成員變量列表
-動態(tài)添加成員變量
-動態(tài)添加屬性
-自動歸檔/解檔
詳細(xì)使用DEMO演示: