LoginSignup
2
4

More than 1 year has passed since last update.

【Swift】RxSwift勉強してみたPart10

Last updated at Posted at 2021-05-17

はじめに

前回
今回は、UITableViewとRxSwiftをバインドしてみたいと思います。

カスタムセルを使わない場合

ScreenShot 2021-05-18 1.41.54.png

ここでバインドしていますね。elementItemの情報が入ってきます

items.bind(to: tableView.rx.items(cellIdentifier: "cell")) { row, element, cell in
    cell.textLabel?.text = element.name
    cell.backgroundColor = element.color
}

カスタムセルを使う場合

カスタムセルを使う場合は、カスタムセルをテーブルビューに登録し、bindの中を以下のように変更します。
cellTypeで作成したカスタムセルを指定しています。

items.bind(to: tableView.rx.items(cellIdentifier: CustomTableViewCell.identifier,
                                  cellType: CustomTableViewCell.self)) { row, element, cell in
    cell.configure(item: element)
}
.disposed(by: disposeBag)

セルは以下のようにしました。

final class CustomTableViewCell: UITableViewCell {
    @IBOutlet private weak var nameLabel: UILabel!

    static var identifier: String { String(describing: self) }
    static var nib: UINib { UINib(nibName: String(describing: self), bundle: nil) }

    func configure(item: Item) {
        nameLabel.text = item.name
        backgroundColor = item.color
    }
}

複数のカスタムセルをIDによって分けたい場合

セルをクロージャの中で生成します。
isEndedは例として、書きました。終わっている時と終わっていない時で表示させるセルを分ける(IDによって)場合を想定しています。

items.bind(to: tableView.rx.items) { tableView, row, element in
    if isEnded {
        let cell = tableView.dequeueReusableCell(withIdentifier: CustomTableViewCell.identifier) as! CustomTableViewCell
        cell.configure(item: element)
        return cell
    } else {
        let cell2 = tableView.dequeueReusableCell(withIdentifier: CustomTableViewCell2.identifier) as! CustomTableViewCell2
        cell2.configure(item: element)
        return cell2
    }
}
.disposed(by: disposeBag)

自作DataSourceを使う場合

こちらは少しだけ、難易度が上がります。

テーブルビューのdidSelectedRowAtなどを実装したいってなった時に使います。

let dataSource = MyDataSource()
items.bind(to: tableView.rx.items(dataSource: dataSource))
    .disposed(by: disposeBag)
final class MyDataSource: NSObject, UITableViewDataSource, RxTableViewDataSourceType {
    typealias Element = [Item]
    var items = [Item]()

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: CustomTableViewCell.identifier,
                                                 for: indexPath) as! CustomTableViewCell
        let item = items[indexPath.row]
        cell.configure(item: item)
        return cell
    }

    func tableView(_ tableView: UITableView, observedEvent: Event<[Item]>) {
        Binder(self) { dataSource, element in
            guard let items = element.element else { return }
            dataSource.items = items
            tableView.reloadData()
        }
        .onNext(observedEvent)
    }
}

データソースクラスを作り、NSObject, UITableViewDataSource, RxTableViewDataSourceTypeの三つに準拠させる。
RxTableViewDataSourceTypetableView(_ tableView: UITableView, observedEvent: Event<[Item]>)を使うための、プロトコルです。
ScreenShot 2021-05-18 7.13.25.png
これを準拠させることにより、tableView(_ tableView: UITableView, observedEvent: Event<[Item]>)には、データがオブザーバーにやってきたときの処理を記述します。
今回の例では、itemsを更新してtableViewをリロードし、描画する処理を記述しています。
そして、onNext()でイベントを流します。
DataSourceを自作する場合の全体のコードを上げておきますGitHub

おわりに

参考記事

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4