RxSwiftでTableView その2
rx_itemsWithCellIdentifierではSection1つしかダメでした。
複数Sectionを使う方法としていくつかあるっぽいのですが、 まずRXTableViewSectionedReloadDataSourceを使ってみます。
RXTableViewSectionedReloadDataSource
これはRxSwiftには含まれておらず別途RxDataSourcesを導入する必要があります。
ViewContorller
import RxSwift import RxCocoa import RxDataSources class MultiListViewController: UIViewController { @IBOutlet weak var tableView: UITableView! @IBOutlet weak var button1: UIButton! private let viewModel = MultiListViewModel() private let dataSource = RxTableViewSectionedReloadDataSource<MySectionModel>() private let disposeBag = DisposeBag() override func viewDidLoad() { dataSource.configureCell = { (_, tableView, indexPath, element) in let cell = tableView.dequeueReusableCellWithIdentifier("Cell1")! cell.textLabel?.text = "\(element) @ row \(indexPath.row)" return cell } viewModel.items.asObservable() .bindTo(tableView.rx_itemsWithDataSource(dataSource)) .addDisposableTo(disposeBag) button1.rx_tap .bindNext { [weak self] in self?.viewModel.change() } .addDisposableTo(disposeBag) } }
ViewModel
RXTableViewSectionedReloadDataSourceをbindせる配列はSectionModelType protocolに対応している必要があります。
import RxSwift import RxCocoa import RxDataSources struct MySectionModel { var rows: [String] init(rows: [String]) { self.rows = rows } } extension MySectionModel: SectionModelType { var items: [String] { return rows } init(original: MySectionModel, items: [String]) { self = original self.rows = items } } class MultiListViewModel { let items = Variable<[MySectionModel]>([]) private var section1 = MySectionModel(rows: ["a", "b", "c"]) private var section2 = MySectionModel(rows: ["A", "B", "C"]) init () { items.value.append(section1) items.value.append(section2) } func change() { items.value[0] = MySectionModel(rows: ["x", "y", "z"]) } }
RXTableViewSectionedReloadDataSourceはその名の通り、Section単位でreloadData()をして表示内容を更新します。 Sectionの中身を変えたいときは上のfunc change()のようにSection毎データを更新してやらないとreloadData()が発火しないようです。
RXTableViewSectionedReloadDataSourceの使い所
- 複数Sectionが扱いたい場合
- Sectionを更新するときはそのSectionまるごとデータを差し替えて支障がないとき
補足
ここではSectionModelTypeプロトコルに対応させたMySectionModelを自分で定義しましたが、 RxSwiftでSectionModelというジェネリクスのstructが用意されているのでそれを使っても実装できます
public struct SectionModel<Section, ItemType>