UITableViewを軽量化する! (Obj-C版）

# 概要
UITableViewのUITableViewDataSourceを分離し、
UIViewControllerを軽くする方法のObj-C版を共有します。

Swift版は、こちら♡
[UITableViewを軽量化する！(Swift版）](http://qiita.com/eKushida/items/92f1fcff65c92e7cc332)

#### *やること*
・UITableViewDataSourceをUIViewContorlllerから分離する

#### *やらないこと*
・UITableViewCellのレイアウトについて
・UITableViewDelegateの分離について

# 実装手順
今回は、テキストを表示するだけのシンプルなTableViewでご説明します。

1. UITableViewDataSouceの拡張クラスを作る
2. UITableViewCellの拡張したクラスを作る
3. UIViewControllerから呼び出す


## 1. UITableViewDataSouceの拡張クラスを作る

```:ItemDataSource.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

typedef void (^TableViewCellConfigureBlock)(id cell, id item);

@interface ItemDataSource : NSObject<UITableViewDataSource>

-(id)initWithItems:(NSArray *)items
    cellIdentifier:(NSString *)cellIdentifier
configureCellBlock:(TableViewCellConfigureBlock)configureCellBlock;

- (id)itemAtIndexPath:(NSIndexPath *)indexPath;

@end
```

```:ItemDataSource.m
#import "ItemDataSource.h"

@interface ItemDataSource ()

@property (nonatomic, strong) NSArray<NSString *> *items;
@property (nonatomic, copy) NSString *cellIdentifier;
@property (nonatomic, copy) TableViewCellConfigureBlock configureCellBlock;

@end

@implementation ItemDataSource

- (id)initWithItems:(NSArray *)items
     cellIdentifier:(NSString *)cellIdentifier
 configureCellBlock:(TableViewCellConfigureBlock)configureCellBlock
{
    self = [super init];
    if (self) {
        self.items = items;っｑ
        self.cellIdentifier = cellIdentifier;
        self.configureCellBlock = [configureCellBlock copy];
    }
    return self;
}

- (id)itemAtIndexPath:(NSIndexPath *)indexPath
{
    return self.items[(NSUInteger) indexPath.row];
}

#pragma mark UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.items.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier
                                                            forIndexPath:indexPath];
    id item = [self itemAtIndexPath:indexPath];
    self.configureCellBlock(cell, item);
    return cell;
}

@end
```

## 2. UITableViewCellの拡張したクラスを作る

```:ItemCell.h
#import <UIKit/UIKit.h>

UIKIT_EXTERN NSString * const CellIdentifier;

@interface ItemCell : UITableViewCell

@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
- (void)configureForCell:(NSString *)title;

@end
```

```:ItemCell.m

#import "ItemCell.h"

@implementation ItemCell

NSString * const CellIdentifier = @"ItemCell";

- (void)configureForCell:(NSString *)title
{
    self.titleLabel.text = title;
}

@end
```

## 3. UIViewControllerから呼び出す
今回作ったItemDataSourceのインスタンスをUITableViewのdataSourceプロパティにセットするだけです。

```:ViewController.m
#import "ViewController.h"
#import "ItemDataSource.h"
#import "ItemCell.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (nonatomic, strong) ItemDataSource *dataSource;
@end

@implementation ViewController

#pragma mark - LifeCycle

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setup];
}

#pragma mark - Private

- (void)setup {
    self.dataSource = [[ItemDataSource alloc]
                             initWithItems:@[@"株式会社",@"スマート",@"デバイス",@"テクノロジー"]
                             cellIdentifier:CellIdentifier
                             configureCellBlock:^(ItemCell *cell, NSString *title) {
                                 [cell configureForCell:title];
                             }];
    
    self.tableView.dataSource = self.dataSource;
}

@end

```

# 完成イメージ

<img width="133" alt="スクリーンショット 2015-12-02 22.56.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/71694/4b3ad814-91ae-4d68-9a13-38296b8341fc.png">

# まとめ
Obj-CもSwift同様
UITableViewDataSourceを分離でき、UIViewControllerの肥大化を防げました。

誤りや、もっとよい方法がございましたら、ご指摘頂ければ幸いです。