2011-07-07 49 views
4

我經常做這樣的事情:Objective-C的forwardInvocation:

CoolViewController *coolViewController = [[CoolViewController alloc] init]; 
[self.navigationController pushViewController:coolViewController animated:YES]; 
[coolViewController release]; 

我將如何,在UINavigationController類別,覆蓋forwardInvocation:,使我可以只而不是做:

[self.navigationController pushCoolViewControllerAnimated:YES]; 
  1. 請在您的答案中包含相關代碼,而不僅僅是解釋。謝謝!

  2. 隨意評論這是否是良好的做法。我也是爲了教育目的而問這個問題,但是在我看來,在這種情況下,代碼簡化可能超過了處理時間的不明顯(正確的)成本。另外,我來自Ruby背景,喜歡使用動態編程來簡化事物,例如Rails中的動態查找器(例如find_by_name)。

  3. 如果您可以實現pushCoolViewControllerAnimated:withBlock,並在初始化視圖控制器後調用該塊,允許我在創建的視圖控制器上設置某些實例變量,則爲獎勵點。

更新:我只記得ARC即將推出。因此,這個具體的例子可能並沒有那麼有用,但仍然是一個很好的練習/例子,可以在其他情況下使用,例如,核心數據動態查找器&傳遞一個塊來配置NSFetchRequest

+10

「請填寫完整的代碼,而不只是一個解釋。」這不是Stack Overflow的意義。 – 2011-07-07 17:21:19

+1

「獎勵積分」?那麼賞金在哪裏呢? – Eimantas

+3

爲什麼您認爲您需要重寫'forwardInvocation:'而不是在'UINavigationController'的類別中創建'pushCoolViewControllerAnimated:'方法? –

回答

14

使用+[NSObject resolveInstanceMethod:] Objective-C的運行時編程手冊中介紹,特別是動態方法解決機制,:

@implementation UINavigationController (FWD) 
+ (BOOL)resolveInstanceMethod:(SEL)sel 
{ 
    NSString *name = NSStringFromSelector(sel); 
    NSString *prefix = @"push"; 
    NSString *suffix = @"Animated:"; 
    if ([name hasPrefix:prefix] && [name hasSuffix:suffix]) { 
     NSRange classNameRange = {[prefix length], 
      [name length] - [prefix length] - [suffix length]} 
     NSString *className = [name substringWithRange:classNameRange]; 
     Class cls = NSClassFromString(className); 
     if (cls) { 
      IMP imp = imp_implementationWithBlock(
      ^(id me, BOOL animated) { 
       id vc = [[cls alloc] init]; 
       [me pushViewController:vc animated:animated]; 
       [vc release]; 
      }); 
      class_addMethod(cls, sel, imp, "[email protected]:c"); 
      return YES; 
     } 
    } 
    return [super resolveInstanceMethod:sel]; 
} 
@end 

當然,如果UINavigationController已經使用+resolveInstanceMethod:,你現在已經打破它。在UINavigationController的子類中執行此操作,或者使用調試方法調用原始實現,可以解決該問題。

接受後創建塊的版本是一個直接的擴展(更改塊參數,更改類型編碼,更改選擇器名稱模式以及如何提取目標類名稱)。

+2

+1這是既可怕又邪惡 – RyanR

+0

謝謝你,傑里米!這正是Stack Overflow的意思。我知道有人會知道如何做到這一點,並願意分享。謝謝! :) – ma11hew28

+0

多數民衆贊成在這麼酷! objc只是越來越好... – twerdster