2012-07-13 9 views
6

私はUITableViewのサブクラスを作成しています。サブクラスで実装されていないすべてのUITableViewDelegateメソッドを転送する前に、実際のデリゲートに渡す前にUITableViewDelegateメソッドのいくつかを処理するようにします。私は私有財産を持つサブクラスで共有UITableViewDelegate

すべて実装されていないメソッドがに転送すべき「本当のデリゲート」を保持します。両方とも私のinitメソッドでは、私は

self.delegate = self; 

を設定し、私は上書き - (無効)setDelegate:(id)をこの

-(void)setDelegate:(id<UITableViewDelegate>)delegate { 
    if (delegate != self) { 
     _trueDelegate = delegate; 
    } else { 
     [super setDelegate:self]; 
    } 
} 

のようにその後、私はメッセージ転送を処理するために、これらをオーバーライドし

-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { 
    NSMethodSignature *sig; 
    sig = [[self.delegate class] instanceMethodSignatureForSelector:aSelector]; 
    if (sig == nil) { 
     sig = [NSMethodSignature signatureWithObjCTypes:"@^v^c"]; 
    } 
    return sig; 
} 

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

問題は、実装されていないデリゲートメソッドがtableviewで呼び出されることはないため、_trueDelegateオブジェクトに転送される機会が与えられていないことです。

私はここでそれらをチェックしてみました:

- (BOOL)respondsToSelector:(SEL)aSelector { 

} 

が、それはうまく他の方法をキャッチが、その方法は、UITableViewDelegate法のために呼び出されることはありません。

+0

デリゲートプロトコルに準拠して拡張クラスを宣言しましたか? –

+0

私は、delegateメソッドを呼び出すときにtableViewが 'respondsToSelector:'の代わりに 'conformsToProtocol:'を使用する可能性があるので尋ねます。 –

+0

本当に私は、非常によく問題になる可能性がある、私はそれをチェックします – Lance

答えて

12

パフォーマンスのために、UITableViewは、デリゲートが設定されるとすぐに利用可能なデリゲートメソッドをチェックして覚えています。デリゲートselfを最初に設定し、次にtrueDelegateを設定します。したがって、代理人がUITableViewに設定された時点で、trueDelegatenilであり、したがって-respondsToSelector:は常にNOを返します。

これを修正するには、trueDelegateが設定された後にデリゲートを設定します。また、転送コードを簡素化することもできます。プロパティを除いて上記以外のコードをすべて削除して置き換えます。

- (void)setDelegate:(id <UITableViewDelegate>)delegate 
{ 
    if (delegate == self) return; 

    self.trueDelegate = delegate; 
    [super setDelegate:self]; 
} 

- (BOOL)respondsToSelector:(SEL)aSelector 
{ 
    if ([super respondsToSelector:aSelector]) return YES; 

    return [self.trueDelegate respondsToSelector:aSelector]; 
} 

- (id)forwardingTargetForSelector:(SEL)aSelector 
{ 
    return self.trueDelegate; 
} 
+0

ありがとう!これは完璧なことですが、好奇心が強いのですが、UITableViewの最適化についてはどうお知りましたか? – Lance

+0

デリゲートを適切に実装する方法を検討したとき、私は以前にそれを見つけました。 'UITableView.h'の' _tableFlags'は、 'UITableView'がデリゲート/データソースに実装されているメソッドをキャッシュするというヒントを提供します。 –

+1

恐ろしい答え、あなたのヒントを得るまですべてを試しました。 –