runtime 消息調(diào)用機(jī)制

  • 在對象調(diào)用方法是Objective-C中經(jīng)常使用的功能,也就是消息的傳遞,而Objective-C是C的超集,所以和C不同的是,Objective-C使用的是動(dòng)態(tài)綁定,也就是runtime。

方法調(diào)用流程

1、編譯器會(huì)把 [self doSomething] 轉(zhuǎn)化objc_msgSend(ViewController,SEL),SEL為@selector(doSomething)。
2、Runtime會(huì)在self對象所對應(yīng)的ViewController類的方法緩存列表里查找方法的SEL(cache)
3、如果沒有找到,則在ViewController類的方法分發(fā)表查找方法的SEL。(類由對象isa指針指向,方法分發(fā)表即method_list)
4、如果沒有找到,則在其父類的方法分發(fā)表里查找方法的SEL
(父類由類的superClass指向)
5、如果沒有找到,則沿繼承體系繼續(xù)下去,最終到達(dá)NSObject類。
6、如果在2345的其中一步中找到,則定位了方法實(shí)現(xiàn)的入口,執(zhí)行具體實(shí)現(xiàn)
7、如果還是沒找到那就會(huì)面臨兩種情況:
① 如果是使用[self doSomething]的方式調(diào)用方法 ② 使用[self performSelector:@selector(doSomething)]的方式調(diào)用方法
對與①情況編譯器會(huì)直接報(bào)錯(cuò),而對于②情況需要到運(yùn)行時(shí)才能確定對象能否接收指定的消息,這時(shí)候會(huì)進(jìn)入下面所說的消息轉(zhuǎn)發(fā)的流程;

消息轉(zhuǎn)發(fā)

  • 1.IMP是”implementation”的縮寫,它是objetive-C 方法(method)實(shí)現(xiàn)代碼塊的地址,可像C函數(shù)一樣直接調(diào)用。通常情況下我們是通過[object method:parameter]或objc_msgSend()的方式向?qū)ο蟀l(fā)送消息,然后Objective-C運(yùn)行時(shí)尋找匹配此消息的IMP,然后調(diào)用它

  • 2.Objetive-C中的Method結(jié)構(gòu)
    在Objecitve-C中,在類中對每一個(gè)方法有一個(gè)在運(yùn)行時(shí)構(gòu)建的數(shù)據(jù)結(jié)構(gòu),在Objective-C 2.0中,此結(jié)構(gòu)對用戶不可見,但仍在內(nèi)部存在。

struct objc_method { SEL method_name ;//方法名為此方法的簽名 char *method_types ;//方法類型描述了參數(shù)的類型。 IMP method_imp ;//函數(shù)指針,為方法具體實(shí)現(xiàn)代碼塊的地址 }

消息轉(zhuǎn)發(fā).png
  • 階段一

+ (BOOL)resolveInstanceMethod:(SEL)sel { if (sel == @selector(doSomething)) { NSLog(@"add method here"); class_addMethod([self class],sel, (IMP)dynamicMethodIMP,"v@:"); return YES; } return [super resolveInstanceMethod:sel]; }

  • 階段二
    這時(shí)候已經(jīng)默許了你并不想使用消息接收者來響應(yīng)這個(gè)方法,所以我們需要找到一個(gè)接盤俠

- (id)forwardingTargetForSelector:(SEL)aSelector { Class class=NSClassFromString(@"BBViewController"); UIViewController *vc = class.new; if (aSelector == NSSelectorFromString(@"secondVCMethod")){ NSLog(@"secondVC do this !"); return vc; } return nil; }

  • 階段三
    runtime需要生成一個(gè)methodSignature變量來組裝,這將通過調(diào)用消息接收者的-(NSMethodSignature *)methodSignatureForSelector:
    獲取,這個(gè)變量包含了方法的參數(shù)類型、參數(shù)個(gè)數(shù)以及消息接收者等信息。接著把這個(gè)變量組裝成一個(gè)NSInvocation對象進(jìn)行最后一次的消息轉(zhuǎn)發(fā),調(diào)用接收者的-forwardInvocation: 來進(jìn)行最后的挽救機(jī)會(huì)

(void)forwardInvocation:(NSInvocation *)anInvocation { Class class=NSClassFromString(@"BBViewController"); UIViewController *vc = class.new; if ([class instancesRespondToSelector:anInvocation.selector]) { [anInvocation invokeWithTarget:vc]; } }

參考文章
http://www.cocoawithlove.com/2008/02/imp-of-current-method.html
延伸
https://github.com/bang590/JSPatch/blob/master/README-CN.md

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

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,030評論 0 9
  • 繼上Runtime梳理(四) 通過前面的學(xué)習(xí),我們了解到Objective-C的動(dòng)態(tài)特性:Objective-C不...
    小名一峰閱讀 838評論 0 3
  • 我們常常會(huì)聽說 Objective-C 是一門動(dòng)態(tài)語言,那么這個(gè)「動(dòng)態(tài)」表現(xiàn)在哪呢?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,319評論 0 7
  • 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的...
    西木閱讀 30,872評論 33 466
  • 少熬夜 少熬夜 少熬夜 少熬夜 少熬夜 少熬夜 少熬夜 少熬夜啊~~~
    黑與白的故事閱讀 211評論 0 0

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