2013-08-21 29 views
1

我有一個視圖控制器,它定義了一個協議本身繼承另一個協議。 我想要任何實現我的協議的對象也實現繼承的協議。目標C與forwardingTargetForSelector轉發並不總是工作的消息

我想設置我的課攔截一些在繼承協議的消息以內部配置一些東西,但最終還是希望所有的郵件轉發到我班的代表

我可以寫許多鍋爐板代碼來存留所有的協議和實習生致電委託,但我看到它打破了很多時間 - 任何時候「超級」協議的變化我需要再次重新設置這個類。

我看到這在自定義用戶界面控件中非常佔優勢。在重用現有組件(例如表或集合視圖)時,您希望數據源響應所有常用協議,但有些實例需要根據索引配置視圖或保存特定狀態。

我以轉發我不迴應消息使用forwardingTargetForSelector試過,但它並不總是轉發...

這裏是一個人爲的代碼示例:

Class A: (the top most protocol) 

@ 

    protocol classAProtocol <NSObject> 

    -(void)method1; 
    -(void)method2; 
    -(void)method3; 

    @end 

    My Class 

    @protocol MyClassProtocol <classAProtocol> 

    -(void)method4; 
    @end 

    @interface MyClass 

    @property (nonatomic,weak> id <MyClassProtocol> delegate; 

    @end 

    @interface MyClass (privateInterface) 

    @property (nonatomic,strong) ClassA *classAObject; 
    @end 
    @implementation MyClass 

    -(init) 
    { 
     self = [super init]; 
     if (self) 
     { 
     _classAObject = [[ClassA alloc] init]; 
     _classAObject.delegate = self; // want to answer some of the delegate methods but not all 
     } 
    } 

-(void)method1 
{ 
    // do some internal configuration 
    // call my delegate with 
    [self.delegate method1]; 
} 
    -(id)forwardingTargetForSelector:(SEL)aSelector 
    { 
     if ([self respondsToSelector:aSelector]) 
     { 
      return self; 
     } 
     if ([self.delegate respondsToSelector:aSelector]) 
     { 
      return self.delegate; 
     } 
     return nil; 
    } 

    -(void)setDelegate:(id <MyClassProtocol>)delegate 
    { 
     self.delegate = delegate; // will forward some of the messages 
    } 
    @end 
+0

將嘗試您的解決方案,並送還給你。 –

回答

0

你不應該從forwardingTargetForSelector:return self;。你的支票應該意味着它永遠不會是,但如果你曾經回報self它會導致無限循環。

您需要確保超級類沒有實現該方法,因爲這會阻止調用forwardingTargetForSelector:。檢查方法是否被實際調用。

forwardingTargetForSelector:也只有在您的控制器上調用一個方法時才被調用,它不會響應。在你的例子中,你不是調用[self ...];,你打電話[self.delegate ...];,所以forwardingTargetForSelector:將不會被調用。

+0

不清楚你說什麼。如果我在我的課上說self.someObject.delegate = self; 而不是實現它的委託將消息不被轉發給我的代表,這是預期執行它? –

+0

方法不會被轉發到不同的對象,除非您編寫一些代碼來實現它。如果你調用'self'並且不實現這個方法(並且一個超類沒有實現它),那麼你的'forwardingTargetForSelector'就會轉發它。 – Wain

2

forwardingTargetForSelector:返回自己是沒有意義的,因爲如果自己對選擇器作出響應,它永遠不會被調用。

您需要實現以下三種方法:

- (void)forwardInvocation:(NSInvocation *)anInvocation 
{ 
    if ([self.delegate respondsToSelector:[anInvocation selector]]) 
     [anInvocation invokeWithTarget:self.delegate]; 
    else 
     [super forwardInvocation:anInvocation]; 
} 

- (BOOL)respondsToSelector:(SEL)aSelector 
{ 
    return [super respondsToSelector:aSelector] || [self.delegate respondsToSelector:aSelector]; 
} 

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector 
{ 
    NSMethodSignature *signature = [super methodSignatureForSelector:selector]; 
    if (!signature) { 
     signature = [self.delegate methodSignatureForSelector:selector]; 
    } 
    return signature; 
} 
+0

添加了這些實現。不確定第三個方法的作用(methodSignatureForSelector)。該選擇器應該是相同的委託不應該呢?另外如果委託沒有實現調用[self.delegate methodSignatureForSelector:selector]的方法;不編譯 –

+0

構建NSInvocation時系統使用它。這將解釋我提供的代碼背後的所有內容:https://developer.apple.com/library/ios/DOCUMENTATION/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtForwarding.html – atomkirk