76
70

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-04-09

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

76
70
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
76
70

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?