TableViewのDataSourceとDelegateをViewControllerから分離

## はじめに
* tableViewを使う場合, datasourceとdelegateを使って、セルの設定やテーブルのデータを設定します.
* その結果, 以下のような感じになりがち

```ViewController.swift

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!
    override func viewDidLoad() {
        super.viewDidLoad()
       
        tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 20
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
        cell.textLabel?.text = String(indexPath.row)
        return cell
    }
}
```

* 最低限のデリゲートのみしか書いてませんが、どんどん増やしていくと見づらいコードになりがちです。
* そこで、これらのdelegateとdatasourceをViewControllerから分離しましょう!がこの記事でお伝えすることです.

## 実装

* `TableViewController.swift`と`TableViewDataSourceDelegateController.swift`の2つに分けました.
* `TableViewDataSourceDelegateController.swift`にdelegateとdatasourceを書いています.

* tableviewはxibファイルで作成し, UIViewにサブビューとして追加しています.
* tableviewcellもxibで作成しています.


```TableViewController.swift
import UIKit

class TableViewController: UIViewController {

    
    let tableView = UINib(nibName: "TableView", bundle: nil).instantiate(withOwner: self, options: nil).first as! UITableView

    var tableViewDataSourceDelegate: TableViewDataSourceDelegateController = TableViewDataSourceDelegateController()
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "tableViewCell")
        
        tableView.delegate = tableViewDataSourceDelegate
        tableView.dataSource = tableViewDataSourceDelegate
        
        self.view.addSubview(tableView)
    }
    

}
```


```TableViewDataSourceDelegateController.swift
import UIKit

typealias UITableViewDD = UITableViewDelegate & UITableViewDataSource

class TableViewDataSourceDelegateController: UITableView, UITableViewDD {

    
    var tableData: [[String]] = [
        ["a", "b", "c"],
        ["d", "e"],
        ["f"],
        ["g", "h", "i", "j", "k"],
    ]
    
    
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        return nil
    }
    
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 20
    }
    
    func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        return nil
    }
    func numberOfSections(in tableView: UITableView) -> Int { // sectionの数を決める
        return tableData.count
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return tableData[section].count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath)

        cell.textLabel?.text = tableData[indexPath.section][indexPath.row]
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("didSelectRowAt: \(indexPath)")
        
        // タップ後すぐ非選択状態にするには下記メソッドを呼び出します．
        tableView.deselectRow(at: indexPath, animated: true)
    }

}
```


## 最後に
* インターンで学んだことを思い出しながら書いています.
* ViewControllerの肥大化を抑えられるのはありがたいです.
* 記事作成にあたって, 作成したプロジェクトをGitHubにおいてあります.
[GitHubレポジトリ](https://github.com/yodaaa/SplitDataSourceTableView/tree/master/SplitDataSourceTableView)

## 参考
[tableView delegate/dataSourceを別ファイルにする場合のコツ](https://qiita.com/BOPsemi/items/4a13f9afd74421a8221f)
[swiftでDelegate/DataSourceを分離したいときに気をつけること](https://qiita.com/terrierscript/items/13133d4318f87ff0acb5)