消息轉發

如果一直到root class都沒有定位到SEL的實現,那么轉入消息轉發過程。

消息轉發流程圖

步驟一:動態解析

通過實現resolveInstanceMethod:resolveClassMethod:方法,我們有機會為該未知消息(SEL)新增一個“處理方法”(IMP)。

這意味著在消息轉發前,你有機會通過class_addMethod給類動態添加一些方法

實際上返回值YES/NO無關緊要,只要你在resovle過程中新增過方法,就會觸發class_getMethodImplementation,其作用相當于重新啟動一次消息發送過程。

步驟二:備用接收者

通過實現-forwardingTargetForSelector:方法將消息(SEL)直接轉發給另一個對象(備用接收者),也就是在另一個對象(不能是nil或self)上重啟消息發送過程。

步驟三:完整轉發

通過實現-methodSignatureForSelector:提供方法簽名(即參數和返回值的類型信息)

可通過調用其他類的+instanceMethodSignatureForSelector:方法或其他對象的-methodSignatureForSelector:方法提供

也可通過+signatureWithObjCTypes:自行生成

生成的簽名將和原始消息一起打包到一個NSInvocation對象中。

通過操作NSInvocation對象的target、selector屬性可以方便地轉發,甚至轉發給另一個對象的另一個需要不同參數的SEL也是可以的

通過-getArgument:atIndex:-setArgument:atIndex:可以操作方法調用傳入的參數

通過-getReturnValue:-setReturnValue:可以直接操作方法invoke后的返回值。

實現-forwardInvocation:方法

通過調用-invoke方法重新啟動一個消息發送過程。

不調用invoke,吞掉這個消息(不做任何處理)

3 轉發的功能

轉發和多繼承

轉發模擬了繼承,所以可以用來為Objc程序提供類似多繼承的功能。轉發和多繼承的區別如下:

? 多繼承是將許多功能combine到一個對象中;

? 轉發則將功能分解到多個對象,并一種對消息發送者透明的方式將它們關聯起來;

代理/替代對象

場景描述:當你有一個對象,這個對象的設置由于需要處理大量數據非常耗時,所以更傾向于懶加載——在真正需要或系統空閑的時候來進行加載,這時你需要一個占位對象來使得應用的其他部分正常工作,這個占位對象的工作如下:

? 獲取關于待加載數據的描述信息

? 轉發消息時檢測對象是否創建并已加載完數據,據此決定創建對象、丟棄消息或轉發消息。

轉發和繼承

以下方法只考慮類繼承體系(不含轉發鏈);如需要對象表現得和繼承一樣,重寫它們并把轉發算法包括進來:

? -respondsToSelector: & +instancesRespondToSelector:

? -isKindOfClass: & -isMemberOfClass:

? -conformsToProtocol:

總結:

消息機制:繼承體系搜索 -> 消息轉發 ( 動態解析-> 快速轉發 -> 完整轉發 )

轉發和繼承(-respondsToSelector:等)、多繼承、代理

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 轉至元數據結尾創建: 董瀟偉,最新修改于: 十二月 23, 2016 轉至元數據起始第一章:isa和Class一....
    40c0490e5268閱讀 1,768評論 0 9
  • 對象在收到無法解讀的消息會發生什么? 若想令類理解某條消息,必須有對應的實現方法.但是,在編譯期間動態像對象添加方...
    有一種再見叫青春閱讀 594評論 0 2
  • 最近開始學習Runtime相關的內容.之前的話知道OC是一門動態的語言(動態類型,動態綁定,動態加載),卻不知道到...
    kikido閱讀 1,846評論 0 1
  • 消息轉發三部曲: 接上面消息發送,如果當前類和父類中都沒有找到實現,那么就會開始嘗試動態方法解析。 動態方法解析 ...
    s_在路上閱讀 2,197評論 2 14
  • 書上說當你處在低谷時不妨多出來走走看看,于是我便像被放風一般從自我的世界里走了出來,一切都是美好的,一切都是...
    紅豆面包淡咖啡閱讀 136評論 0 0