Arrayのメソッドを持っていて、保持している要素が変化したときにはメッセージを投げる配列っぽいものをつくりました。
最新のRxSwift 2.2に対応しており、PodとCarthageで利用可能です。
基本的な使いかた
こんな感じで宣言します。
var array: ObservableArray<String> = ["foo", "bar", "buzz"]
ObservableArrayには、Rxのメッセージ用のメソッドrx_elements()とrx_events()を持っています。
func rx_elements() -> Observable<[Element]> // 要素全体 func rx_events() -> Observable<ArrayChangeEvent> // 差分によるイベント
通常のRxSwiftのようにsubscribeして使えます。
array.rx_events().subscribeNext { print($0) }
rx_eventsは変化した後の配列の要素すべてを投げますので、ここから、次のようにメソッドを呼ぶと、
array.append("coffee")
array[2] = "milk"
array.removeAll()
次のような結果が表示されるはずです。
["foo", "bar", "buzz", "coffee"] ["foo", "bar", "milk", "coffee"] []
UITableViewでの表示
rx_itemsWithCellIdentifierと組み合わせると、次のような感じで使えるようになるはずです。
model.rx_elements()
.observeOn(MainScheduler.instance)
.bindTo(tableView.rx_itemsWithCellIdentifier("MySampleCell")) { (row, element, cell) in
guard let c = cell as? MySampleCell else { return }
c.model = self.model[row]
return
}
.addDisposableTo(disposeBag)
rx_events
rx_eventsは変化の差分の情報を配列を投げます。
ArrayChangeEvent(insertedIndeces: [3], deletedIndeces: [], updatedIndeces: []) ArrayChangeEvent(insertedIndeces: [], deletedIndeces: [], updatedIndeces: [2]) ArrayChangeEvent(insertedIndeces: [], deletedIndeces: [0, 1, 2, 3], updatedIndeces: [])
この結果を見ればわかるように、インデックスベースでの結果が返されます。
なので、UITableViewのinsertRowsAtIndexPaths、deleteRowsAtIndexPaths、reloadRowsAtIndexPathsなどを使ってアニメーションも頑張ればできます。
func toIndexSet(array: [Int]) -> [NSIndexPath] {
return array.map { NSIndexPath(forRow: $0, inSection: 0) }
}
self.beginUpdates()
self.insertRowsAtIndexPaths(toIndexSet(event.insertedIndeces), withRowAnimation: .Automatic)
self.deleteRowsAtIndexPaths(toIndexSet(event.deletedIndeces), withRowAnimation: .Automatic)
self.reloadRowsAtIndexPaths(toIndexSet(event.updatedIndeces), withRowAnimation: .Automatic)
self.endUpdates()
完全な例はGitHubのReadmeを参照してください。
ちなみに、rx_itemsWithCellIdentifierが内部でreloadData()を呼んでしまうので、
アニメーションをしたければrx_itemsWithCellIdentifierと絡めて利用できませんのでご注意を。
その他
CollectionType準拠していたりするのでsortなども使えます。

0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。