Edited at

RxSwift/RxCocoa Driver Unitについてまとめてみた。

More than 3 years have passed since last update.


Driver Unitについてまとめてみた

川を引き始めて3ヶ月、ようやくDriverについて少しわかってきたので自身の理解を深めるために一度まとめてみた。


Driver Unitとは

DriverはUIに特化されている!!

Driverの特徴

1.エラーでストリームが終了しない

2.メインスレッドで行われる

3.サイドエフェクトをシェアする(あまりよくわかっていない)

Driver Unitの一番の特徴はエラーが起きない事です!(正確にはエラーを購読して[ ]を返している)。Observableを使っていた場合ErrorCompletedでストリームが終了してしまうが、Driver(asDriver)の場合はエラーが流れてきた場合は適当なものを返して購読を続けてくれます。なのでAPI通信などがエラーだった場合でもストリームが終了する事なく購読が続きます。


Example


Sample


@IBOutlet weak var textField: UITextField!
@IBOutlet weak var resultLabel: UILabel!

let result = textField.rx_text
.flatMapLatest { text in
//API通信
}

result
.map { $0.description }
.bindTo(resultLabel.rx_text)
.addDisposableTo(disposeBag)

result
.bindTo(tableView..rx_itemsWithCellIdentifier("Cell")) { _, result, cell in
cell.textLabel?.text = "\(result.totalCount)"
}
.addDisposableTo(disposeBag)


上記のサンプルだとflatMapLatest内でエラーが起こったらストリームが終了してしまいresultが更新されてもUIは更新されません。そしてAPI通信がメインスレッド以外で行なわれているとクラッシュの原因にもなります!

そして上記の場合だと1つのストリームを二つのUIにバインドしているので2回HTTPリクエストが送られています。

ではこれらの問題をふまえてsample2を書いてみましょう


sample2

@IBOutlet weak var textField: UITextField!

@IBOutlet weak var resultLabel: UILabel!

let result = textField.rx_text
.flatMapLatest { text in
//API通信
.observeOn(MainScheduler.instance)
.catchErrorJustReturn([])
}
.shareReplay(1)

result
.map { $0.description }
.bindTo(resultLabel.rx_text)
.addDisposableTo(disposeBag)

result
.bindTo(tableView..rx_itemsWithCellIdentifier("Cell")) { _, result, cell in
cell.textLabel?.text = "\(result.totalCount)"
}
.addDisposableTo(disposeBag)


.observeOn(MainScheduler.instance)を使う事でメインスレッドで行う事を保証し、エラーの時には.catchErrorJustReturn([])を使って[]returnします。catchError { _ in Observable.empty() }でもエラーで購読を終了しないようにエラー処理ができる。

1回のリクエストの結果を2つのUIにシェアするためにここでは.shareReplay(1) を使って処理をしています。

では最後にDriverを使って同じ処理を行ってみましょう。


sample2

@IBOutlet weak var textField: UITextField!

@IBOutlet weak var resultLabel: UILabel!

let result = textField.rx_text.asDriver
.flatMapLatest { text in
//API通信
.asDriver(onErrorJustReturn: [])
}

result
.map { $0.description }
.Drive(resultLabel.rx_text)
.addDisposableTo(disposeBag)

result
.Drive(tableView..rx_itemsWithCellIdentifier("Cell")) { _, result, cell in
cell.textLabel?.text = "\(result.totalCount)"
}
.addDisposableTo(disposeBag)



まとめ

Driverが行う事

1. .observeOn(MainScheduler.instance) メインスレッドで行う

2. .catchErrorJustReturn(onErrorJustReturn) 絶対にエラーで購読が終了しない

3. .shareReplayLatestWhileConnected サイドエフェクトをシェアする(やっぱりあまり理解できていない)

3つめのサイドエフェクトをシェアするに関する事でなにかありましたらコメントをいただけると幸いです。