RxDataSourceを使ってみるサンプル

[RxDataSources](https://github.com/RxSwiftCommunity/RxDataSources)を見ながら適当なTableViewを作る

![Simulator Screen Shot - iPhone 8 Plus - 2018-01-04 at 18.27.53.png](https://qiita-image-store.s3.amazonaws.com/0/224958/6cfe4278-ebc1-a4fd-e7b4-c7d1980877b1.png)

# 手順
## 1. Modelの作成

以下のようなModelがあるとする。

```swift
struct CustomData {
    var str: String
}
```

TableViewのSectionを表すための構造体を作る

```swift
struct SectionOfCustomData {
    var header: String
    var items: [Item]
}

extension SectionOfCustomData: SectionModelType {
    typealias Item = CustomData
    
    init(original: SectionOfCustomData, items: [SectionOfCustomData.Item]) {
        self = original
        self.items = items
    }
}
```

`SectionOfCustomData`は`SectionModelType`に準拠する必要がある。

## 2. ViewControllerの作成

StoryboardでViewControllerの上にTableViewをおく。
Storyboard上でdatasource/delegateの設定は**行わないこと**。

ViewControllerのコードは以下のようになる。

```swift
import UIKit
import RxSwift
import RxDataSources

class ViewController: UIViewController, UITableViewDelegate {
    
    @IBOutlet weak var tableView: UITableView!
    var dataSource: RxTableViewSectionedReloadDataSource<SectionOfCustomData>!
    let d = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.rx.setDelegate(self).disposed(by: d)
        setupDataSource()
        bindModels()
    }
    
    func setupDataSource() {
        dataSource = RxTableViewSectionedReloadDataSource<SectionOfCustomData>(configureCell: {
            (ds: TableViewSectionedDataSource<SectionOfCustomData>, tableView: UITableView, indexPath: IndexPath, model: CustomData) -> UITableViewCell in
            
            let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
            cell.textLabel?.text = model.str
            return cell
        })
        dataSource.titleForHeaderInSection = { ds, index in
            return ds.sectionModels[index].header
        }
    }
    
    func bindModels() {
        let sections = [
            SectionOfCustomData(header: "First section",
                                items: [CustomData(str: "zero"),
                                        CustomData(str: "one") ]),
            SectionOfCustomData(header: "Second section",
                                items: [CustomData(str: "two"),
                                        CustomData(str: "three") ])
        ]
        Observable.just(sections)
            .bind(to: tableView.rx.items(dataSource: dataSource))
            .disposed(by: d)
    }
}

```

### DataSourceの設定をする
`setupDataSource()`では表示されるCellの設定をします。

以下のメンバにクロージャをセットします。

* `configureCell` (required) : Cell
* `titleForHeaderInSection` : セクションヘッダ
* `titleForFooterInSection` : セクションフッタ
* etc

### ModelをBindする
Modelを適当に作って、SectionOfCustomDataを作成しDataSourceにBindします。

以上

# `UITableViewDelegate`, `UITableViewDataSource`を使ってみる
同じことを`UITableViewDelegate`, `UITableViewDataSource`を使って書いてみた。

```swift
import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    let sections = [
        SectionOfCustomData(header: "First section",
                            items: [CustomData(str: "zero"),
                                    CustomData(str: "one") ]),
        SectionOfCustomData(header: "Second section",
                            items: [CustomData(str: "two"),
                                    CustomData(str: "three") ])
    ]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.delegate = self
        tableView.dataSource = self
    }
}

extension ViewController: UITableViewDataSource {
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return sections.count
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return sections[section].items.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let model = sections[indexPath.section].items[indexPath.row]
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel?.text = model.str
        
        return cell
    }
}

extension ViewController: UITableViewDelegate {
    
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return sections[section].header
    }
}

```


# 個人的な感想
今回はCellやModelがシンプルなので一概には言えないけど

* なれている方が使いやすい。
    * お作法的な書き方がやっぱり覚えやすくない。
* RxDataSource使えば`numberOfxxx`とか書かなくてよくて楽。
* 書きながらデバッグして見た目を調整したい時とかは`UITableViewDelegate`, `UITableViewDataSource`使う方が向いている気がする。
* いろんなCell, 同一Section内に複数種類のCellがあるときはまた今度試そうと思う。