編寫高質量OC程式碼52建議總結:12.理解訊息轉發機制

viiimaus發表於2017-02-13
訊息轉發分為兩個階段
    --第一階段,先問接受者所屬的類,能否動態新增方法處理當前“未知的選擇器”,這叫做“動態方法解析”。
    --第二階段,“完整的訊息轉發機制”,首先請接受者看看有沒有其他物件能處理這條訊息,如果有,則把訊息轉給那個物件,訊息轉發過程結束。如果沒有“備用接受者”,則啟動完整的訊息轉發機制,系統會把與訊息有關的所有細節封裝到 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.如果還沒辦法處理選擇子,那就啟動完整的訊息轉發機制。

相關文章