2016/02/18

RxSwift用のObservableなArrayをつくった

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: [])

この結果を見ればわかるように、インデックスベースでの結果が返されます。

なので、UITableViewinsertRowsAtIndexPathsdeleteRowsAtIndexPathsreloadRowsAtIndexPathsなどを使ってアニメーションも頑張ればできます。

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 件のコメント:

コメントを投稿

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