tableViewの中にtableViewを入れ子にする方法

# tableViewの入れ子構造
縦にスクロールするtableViewの特定の行のセルを、横にスクロールするtableViewのコンテンツにしたかったので、方法を調べました。イメージとしては、以下のようになります。

![tableView入れ子.001.jpg](https://qiita-image-store.s3.amazonaws.com/0/50474/cb19a860-d9ad-c51d-15ed-c4752488c486.jpeg)


# 基本的な考え方
基本的には、ViewControllerの中にverticalTableViewがいて、ViewControllerにコントロールを委譲しています。そこでverticalTableViewにverticalTableViewCellを入れます。

verticalTableViewCellには、horizontalTableViewがaddされています。
horizontalTableViewは、 ~~ViewController~~ verticalTableViewCellにコントロールを委譲していて、horizontalTableViewCellを入れています。またhorizontalTableViewのコンテンツおよびスクロール方向を横向きに変更しています。

~~ViewControllerで２種類のtableViewを制御することになるので、verticalとhorizontalのどちらのtableViewなのかを判別して、処理を分岐させる必要があります。
私の場合はtagで判別しました。~~ ２つのtableViewを一つのViewControllerで制御するのは複雑なので、修正しました。

# コード

```objc:ViewController.h
#import <UIKit/UIKit.h>
#import "VerticalTableViewCell.h"

@interface ViewController : UIViewController<UITableViewDelegate, UITableViewDataSource>

@property (strong, nonatomic) IBOutlet UITableView *verticalTableView;

@end
```

```objc:ViewController.m
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // verticalTableViewのdelegate等を設定
    self.verticalTableView.delegate = self;
    self.verticalTableView.dataSource = self;
    
    // セルの再利用登録
    [self.verticalTableView registerClass:[VerticalTableViewCell class]
                   forCellReuseIdentifier:@"vertical"];
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // verticalの場合
    // verticalのセルを生成
    VerticalTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"vertical"];
    [cell buildHorizontalTableView];
    
    
    // horizontalTableViewに1以上のタグを設定
    cell.horizontalTableView.tag = indexPath.row +1;
    return cell;

}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 10;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 200.0;
}

@end
```


```objc:VerticalTableViewCell.h
#import <UIKit/UIKit.h>

@interface VerticalTableViewCell : UITableViewCell

@property (nonatomic, strong) UITableView *horizontalTableView;
- (void)buildHorizontalTableView;
@end
```

```objc:VerticalTableViewCell.m
#import "VerticalTableViewCell.h"

@implementation VerticalTableViewCell

- (void)buildHorizontalTableView
{
    CGRect frame = CGRectMake(0, 0, 200.0, [UIScreen mainScreen].bounds.size.width);
    self.horizontalTableView = [[UITableView alloc] initWithFrame:frame];
    
    // horizontalセルのdelegate等を設定
    self.horizontalTableView.delegate = self;
    self.horizontalTableView.dataSource = self;
    
    // 横スクロールに変更
    self.horizontalTableView.center = CGPointMake(self.horizontalTableView.frame.origin.x + self.horizontalTableView.frame.size.height / 2, self.horizontalTableView.frame.origin.y + self.horizontalTableView.frame.size.width / 2);
    self.horizontalTableView.transform = CGAffineTransformMakeRotation(-M_PI / 2);
    
    // セルの再利用登録
    [self.horizontalTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"horizontal"];
    
    // tableViewを追加
    [self addSubview:self.horizontalTableView];
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // horizontalのセルを生成
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"horizontal"];
    cell.textLabel.text = [NSString stringWithFormat:@"(%ld,%ld)",tableView.tag -1, indexPath.row];
    
    // セルの向きを横向きに
    cell.contentView.transform = CGAffineTransformMakeRotation(M_PI / 2);
    return  cell;
}


-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 10;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 100.0;
}

@end

```

# 最後に
今まで1つのviewControllerで2つのtableViewを制御することがなかったので、tableViewとViewControllerは1対1だと思い込んでいました。tableViewCellの中のtableViewのコントロールはどこでやればいいのか分からず悩んでいたのですが、なんとか解決できました。delegateの意味をより理解できた気がします。

2015/02/09追記
やはり一つのviewControllerで2つのtableViewを制御するのは、制御が複雑になるので、よろしくないようです。UITableViewDelegateなどのprotocolをUITableViewCellのカスタムクラスに宣言することで、簡単にできるようです。

# 参考
[(iOS/iPhoneアプリ開発) UITableViewを使って横スクロールビューを作成](http://development.hatenadiary.com/entry/20131220/1387527548)
[UITableViewまわりのきほん]
(http://qiita.com/mag4n/items/bcdf1e88794317cf8c9c)

# リポジトリ
https://github.com/bohemian916/horizontalScrollTableView