2011-11-07 58 views
5

我只是在研究Objective-C的「消息轉發」。我編寫了一個測試程序來驗證是否可以在運行時「吞下」一個無法識別的選擇器。所以我這樣做:如何通過消息轉發「吞下」「無法識別的選擇器錯誤」?

- (void) forwardInvocation: (NSInvocation *) anInvocation { 
    if ([anInvocation selector] == @selector(testMessage)){ 
     NSLog(@"Unknow message"); 
    } 
    return; 
} 

但它仍然會在運行時拋出「無法識別的選擇器」錯誤。搜索分辨率後,我知道我需要重寫方法「methodSignatureForSelector:」所以我寫所謂的「代理」其他代理類和下面的方法:但是

(NSMethodSignature *)methodSignatureForSelector:(SEL)selector { 
    if ([Proxy instancesRespondToSelector: selector]) { 
     return [Proxy instanceMethodSignatureForSelector: selector]; 
    } 
    return [super methodSignatureForSelector:selector]; 
} 

,其實,我不希望實施這樣的另一個代理類來完成這個方法。我想要做的就是忽略這個未知的選擇器。但是,如果我只需鍵入這一點,這是行不通的:

(NSMethodSignature *)methodSignatureForSelector:(SEL)selector { 
    return [super methodSignatureForSelector:selector]; 
} 

所以,我不知道有什麼辦法可以簡單地「吞噬」這個錯誤? (不使用異常處理程序,我想要一個「轉發」的方式)。謝謝!

+0

參考http://stackoverflow.com/a/11531609/ –

回答

3

你可能需要生成一個簽名對象,這是一個有點棘手:

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector { 
    NSMethodSignature *sig = [super methodSignatureForSelector:selector]; 
    if (!sig) { 
     if (selector == @selector(testMessage)) { 
      // Create a signature for our fake message. 
      sig = [NSMethodSignature signatureWithObjCTypes:"@:"]; 
     } 
    } 
    return sig; 
} 

- (void)forwardInvocation:(NSInvocation *)anInvocation 
{ 
    // Do whatever you want with the invocation. 
} 

最大的問題似乎是參數signatureWithObjCTypes:。請參閱Apple's type encoding documentation。每種方法至少有兩個參數:id self(類型@)和SEL _cmd(類型:)。

另一種方法是使用虛擬方法,例如- (void)dummy { },然後使用sig = [super methodSignatureForSelector:@selector(dummy)];來獲取僞造方法的簽名。

+0

它的工作原理!謝謝!但還有一件事:如果我按照你的建議嘗試進行這樣的調用:forwardInvocation:方法中的[anInvocation選擇器],發生錯誤: **由於未捕獲的異常'NSInvalidArgumentException',原因:' - [NSInvocation getArgument :atIndex:]:index(1)out-bounds [-1,0]'**, 爲什麼? –

+3

我發現[this](http://www.cocoabuilder.com/archive/cocoa/289799-nsproxy-nsinvocation-question.html):* [NSMethodSignature signatureWithObjTypes:]的文檔是錯誤的。類型數組中的第一個元素是返回類型,而不是id或Class類型,這實際上給我留下了一個MSMethodSignature實例,它不包含selector參數的參數類型。*這可能意味着對於方法' - (void) foo'您需要在'signatureWithObjCTypes:'的參數中輸入''v @:「''。 – DarkDust

+0

嗯......我明白了......謝謝! –

相關問題