RxSwiftでUITableViewのバインド処理
↑の記事で、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. 実行結果
見事バインドされております。
4. 補足情報
UITableViewのセル押下時のイベントハンドリング用の関数や
セル削除の関数もRxSwiftが提供しているので基本的に前述のProtocolの
実装は不要......ですが、複雑なテーブル作成時にはRxSwiftではサポートが
難しい場合もあるような気がします。
個人的には、SectionHeader対応とかが必要になってきたら
結局はUITableViewDataSourceの実装とかが必要なんだろうな、と。
ただ、単純なテーブル作成であればすごく便利な機能だと思います。