読者です 読者をやめる 読者になる 読者になる

スマートデバイスアプリ開発のあれやこれや

RxSwiftでUITableViewのバインド処理

niwaka.hateblo.jp

 ↑の記事で、UITableViewとのバインド時はセルが再利用されるので
Disposableをdispose関数で無効にする(キリッ)と言ってましたが

 もっと良い方法がありました......。

1. RxSwiftはUITableViewのバインド機能を提供している

 そうなんです。自前でちまちまバインド解除とか不要だったんです。
UITableViewやUICollectionView向けに簡単バインド機能を提供しているのです。

 どのくらい便利かというと......。

  • UITableViewDelegateの実装が不要
  • UITableViewDataSourceの実装が不要


 上記のプロトコルの実装=UITableViewの利用というイメージが
あったので、初めてこの機能を使ったときは半信半疑でした。
でも、RxSwiftを使うと動くのです......。

2. UITableViewとViewModelのバインドを定義する

 UITableViewに表示したいデータを保持するViewModelを定義します。

class ViewModel {
    /**
     仮面ライダーの名前を保持する配列
     */
    var riders = Variable<[String]>([])

    init() {
        riders.value.append("仮面ライダー龍騎")
        riders.value.append("仮面ライダーカブト")
        riders.value.append("仮面ライダーキバ")
        riders.value.append("仮面ライダーアギト")
        riders.value.append("仮面ライダーW")
        riders.value.append("仮面ライダーディケイド")
        riders.value.append("仮面ライダーオーズ")
        riders.value.append("仮面ライダー電王")
        riders.value.append("仮面ライダーウィザード")
    }
}


 そして、バインド対象のUITableViewを保持するController。

import UIKit
import RxSwift
import RxCocoa
import RxBlocking

class ViewController: UIViewController {

    /**
     TableView
     */
    @IBOutlet weak var list: UITableView!
    
    /**
     ViewModel
     */
    let model = ViewModel()
    
    /**
     Bag
     */
    let bag   = DisposeBag()
    
    /**
     Storyboardバインド後処理
     */
    override func viewDidLoad() {
        super.viewDidLoad()
        bindViewAndModel()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    /**
     データバインド処理
     */
    private func bindViewAndModel() {
        // UITableViewとViewModelのバインド
        model.riders.bindTo(list.rx_itemsWithCellIdentifier("CellIdentifier")) { _, riderName, cell -> Void in
            cell.textLabel?.text = riderName
        }.addDisposableTo(bag)
    }

}

3. 実行結果

 見事バインドされております。

f:id:cross-xross:20151117212630p:plain

4. 補足情報

 UITableViewのセル押下時のイベントハンドリング用の関数や
セル削除の関数もRxSwiftが提供しているので基本的に前述のProtocolの
実装は不要......ですが、複雑なテーブル作成時にはRxSwiftではサポートが
難しい場合もあるような気がします。


 個人的には、SectionHeader対応とかが必要になってきたら
結局はUITableViewDataSourceの実装とかが必要なんだろうな、と。


 ただ、単純なテーブル作成であればすごく便利な機能だと思います。