編寫高質量OC程式碼52建議總結:12.理解訊息轉發機制
訊息轉發分為兩個階段
--第一階段,先問接受者所屬的類,能否動態新增方法處理當前“未知的選擇器”,這叫做“動態方法解析”。
--第二階段,“完整的訊息轉發機制”,首先請接受者看看有沒有其他物件能處理這條訊息,如果有,則把訊息轉給那個物件,訊息轉發過程結束。如果沒有“備用接受者”,則啟動完整的訊息轉發機制,系統會把與訊息有關的所有細節封裝到 NSInvocation物件中,再給接受者最後一次機會處理當前訊息。
動態方法解析
該方法引數是那個未知的選擇器,返回值是bool型別,表示這個類是否能新增一個例項方法處理這個選擇器。有機會新增一個處理此選擇器的方法。如果未實現的方法不是例項方法而是類方法。執行期系統就會呼叫另一個方法。
備註:使用這種方法的前提是,相關實現程式碼已經寫好,只等執行時動態插在類裡。
備用接受者
當前接受者還有第二次機會處理未知的選擇器。能不能把這條訊息轉給其他物件處理。
在一個物件內部,可能還有一系列其他物件,該物件可經由此方法將能夠處理某選擇子的相關內部物件返回。
備註:在這一步,無法操作所轉發的訊息。
完整的訊息轉發
首先建立NSInvocation物件,把尚未處理的訊息所有相關細節都封裝其中。包含選擇器、目標、引數。
實現方式:在觸發訊息前,先以某種方式改變訊息內容,比如,追加另外一個引數,或者改變選擇器。
實現此方法時,如果發現呼叫操作不應該由本類操作,則呼叫父類同名方法。繼承體系中每個類都有機會處理此呼叫請求,直到NSObject。最後呼叫了NSObject類的方法,該方法會繼續呼叫“doesNotRecognizeSelector:”,丟擲異常,代表訊息最終未被處理。
訊息轉發全流程
步驟越往後,處理訊息的代價越大。最好能在第一步處理完,執行期系統就可以將此方法快取。第三部只是修改了呼叫目標,這項改動放在第二步會更簡單,不然的話,還得建立並處理完整的NSInvocation。
總結:
--1.若物件無法響應某個選擇子,則進入訊息轉發流程。
--2.通過執行期的動態方法解析功能,我們可以在需要用到某個方法時再將其加入類中。
--3.物件可以把其無法解讀的某些選擇子轉交給其他物件來處理。
--4.如果還沒辦法處理選擇子,那就啟動完整的訊息轉發機制。
--第一階段,先問接受者所屬的類,能否動態新增方法處理當前“未知的選擇器”,這叫做“動態方法解析”。
--第二階段,“完整的訊息轉發機制”,首先請接受者看看有沒有其他物件能處理這條訊息,如果有,則把訊息轉給那個物件,訊息轉發過程結束。如果沒有“備用接受者”,則啟動完整的訊息轉發機制,系統會把與訊息有關的所有細節封裝到 NSInvocation物件中,再給接受者最後一次機會處理當前訊息。
動態方法解析
+(BOOL)resolveInstanceMethod:(SEL)sel
該方法引數是那個未知的選擇器,返回值是bool型別,表示這個類是否能新增一個例項方法處理這個選擇器。有機會新增一個處理此選擇器的方法。如果未實現的方法不是例項方法而是類方法。執行期系統就會呼叫另一個方法。
+(BOOL)resolveClassMethod:(SEL)sel
備註:使用這種方法的前提是,相關實現程式碼已經寫好,只等執行時動態插在類裡。
備用接受者
當前接受者還有第二次機會處理未知的選擇器。能不能把這條訊息轉給其他物件處理。
-(id)forwardingTargetForSelector:(SEL)aSelector
在一個物件內部,可能還有一系列其他物件,該物件可經由此方法將能夠處理某選擇子的相關內部物件返回。
備註:在這一步,無法操作所轉發的訊息。
完整的訊息轉發
首先建立NSInvocation物件,把尚未處理的訊息所有相關細節都封裝其中。包含選擇器、目標、引數。
-(void)forwardInvocation:(NSInvocation *)anInvocation
實現方式:在觸發訊息前,先以某種方式改變訊息內容,比如,追加另外一個引數,或者改變選擇器。
實現此方法時,如果發現呼叫操作不應該由本類操作,則呼叫父類同名方法。繼承體系中每個類都有機會處理此呼叫請求,直到NSObject。最後呼叫了NSObject類的方法,該方法會繼續呼叫“doesNotRecognizeSelector:”,丟擲異常,代表訊息最終未被處理。
訊息轉發全流程
步驟越往後,處理訊息的代價越大。最好能在第一步處理完,執行期系統就可以將此方法快取。第三部只是修改了呼叫目標,這項改動放在第二步會更簡單,不然的話,還得建立並處理完整的NSInvocation。
總結:
--1.若物件無法響應某個選擇子,則進入訊息轉發流程。
--2.通過執行期的動態方法解析功能,我們可以在需要用到某個方法時再將其加入類中。
--3.物件可以把其無法解讀的某些選擇子轉交給其他物件來處理。
--4.如果還沒辦法處理選擇子,那就啟動完整的訊息轉發機制。
相關文章
- 編寫高質量OC程式碼52建議總結:11.理解objc_msgSend的作用(訊息機制)C程式OBJGse
- 編寫高質量OC程式碼52建議總結:17.實現describtion方法C程式
- 編寫高質量OC程式碼52建議總結:16.提供“全能初始化方法”C程式
- 編寫高質量OC程式碼52建議總結:13.用“方法調配技術”除錯“黑盒方法”C程式除錯
- OC訊息機制,訊息轉發機制
- 編寫高質量程式碼:改善Java程式的151個建議(第4章:字串___建議52~55)Java字串
- [轉]高質量JAVA程式碼編寫規範Java
- [編寫高質量iOS程式碼的52個有效方法](九)塊(block)iOSBloC
- 我總結了寫出高質量程式碼的12條建議
- 編寫高質量iOS與OS X程式碼的52個有效方法(一)iOS
- 編寫高質量iOS與OS X程式碼的52個有效方法(五)iOS
- 編寫高質量iOS與OS X程式碼的52個有效方法(二)iOS
- 編寫高質量iOS有效方法總結(一)iOS
- 編寫高質量程式碼 改善Python程式的91個建議Python
- [編寫高質量iOS程式碼的52個有效方法](七)記憶體管理(上)iOS記憶體
- [編寫高質量iOS程式碼的52個有效方法](八)記憶體管理(下)iOS記憶體
- [編寫高質量iOS程式碼的52個有效方法](十)Grand Central Dispatch(GCD)iOSGC
- iOS 編寫高質量Objective-C程式碼iOSObjectC程式
- 怎樣編寫高質量的java程式碼Java
- 編寫高質量的程式碼,從命名入手
- 寫出高質量程式碼的10個建議
- 《編寫高質量程式碼:改善Java程式的151個建議》筆記Java筆記
- [Unity 程式碼寫法整理]訊息機制(三)Unity
- iOS 編寫高質量Objective-C程式碼(四)iOSObjectC程式
- iOS 編寫高質量Objective-C程式碼(一)iOSObjectC程式
- iOS 編寫高質量Objective-C程式碼(三)iOSObjectC程式
- iOS 編寫高質量Objective-C程式碼(二)iOSObjectC程式
- iOS 編寫高質量Objective-C程式碼(八)iOSObjectC程式
- iOS編寫高質量Objective-C程式碼(四)iOSObjectC程式
- iOS編寫高質量Objective-C程式碼(二)iOSObjectC程式
- iOS 編寫高質量Objective-C程式碼(五)iOSObjectC程式
- iOS 編寫高質量Objective-C程式碼(六)iOSObjectC程式
- iOS 編寫高質量Objective-C程式碼(七)iOSObjectC程式
- iOS編寫高質量Objective-C程式碼(六)iOSObjectC程式
- 如何編寫高質量的C#程式碼(一)C#
- 編寫高質量程式碼
- 編寫高質量程式碼:改善Java程式的151個建議(第4章:字串___建議56~59)Java字串
- 分析與理解訊息反射機制 (轉)反射