たとえばUITableViewにはdelegateプロパティがあります。UITableViewのSubclass MyTableViewを作って、UITableViewDelegateの受け取り手になるとします。

@implementation MyTableView

- (id)initWithFrame:(CGRect)frame style:(UITableViewStyle)style
{
  self = [super initWithFrame:frame style:style];
  if (self) {
    self.delegate = self; // MyTableViewがdelegateの受け取り手になる
  }
  return self;
}

@end

次にMyTableViewをオブジェクト化する側もdelegateを通じてイベントを受け取りたいとします。

MyTableView *tableView = [[MyTableView alloc] initWithFrame:CGRectMake(0, 0, 320, 100) style:UITableViewStylePlain];
tableView.delegate = self; // こうしてしまうとMyTableViewがdelegateの受け取り手でなくなってしまう

コメントにも書いたように、こうしてしまうとdelegateに別のオブジェクトが設定され、MyTableViewがイベントを受け取れなくなってしまいます。

ここでmyDelegateとかを別途定義するのはダサいし、delegateのままでUITableViewDelegateのメソッドも受け取りたい。その方法を解説。

Superclassのdelegateを拡張する方法

まずはUITableViewDelegateを拡張してMyTableViewDelegate protocolを定義

@protocol MyTableViewDelegate<UITableViewDelegate>

// カスタムdelegateメソッド
- (void)tableViewDidTapHeaderView:(MyTableView *)tableView;

@end

次にSubclassのprivateメンバー変数として_myDelegateを定義。あくまでprivate変数で外部へは公開しません。

__weak id<MyTableViewDelegate> _myDelegate;

次にSubclassのsetDelegateをオーバーライド。

- (void)setDelegate:(id<UITableViewDelegate>)delegate {
  if (self.delegate == self) {
    // 自身をdelegateとする場合は、Superclassのdelegateに設定 
    [super setDelegate:self]; 
  } else { 
    // それ以外は_myDelegateに設定 
    _myDelegate = delegate; 
  } 
}

このようにすることでdelegateの設定先を内部で切り分けます。

もしMyTableViewDelegateでUITableViewDelegateのdelegateメソッドを受け取りたい場合は以下のようにフォワードします。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([_myDelegate respondsToSelector:@selector(tableView:didSelectRowAtIndexPath:)]) {
        // Forward UITableViewDelegate to MyTableViewDelegate
        [_myDelegate tableView:tableView didSelectRowAtIndexPath:indexPath];
    }
}

今回のサンプルはgithubにコミットしてあります。

https://github.com/stack3/STExtendDelegateSample