ReactiveX 學習筆記(37)RxSwift 的 share 和 RxCocoa 的 Driver
冷數據流,熱數據流
- 冷數據流不能共享數據,熱數據流能共享數據
- 冷數據流需要有訂閱者才能發布數據,熱數據流無需訂閱者即可發布數據
publish, connect, refCount, replay
Understanding Connectable Observable Sequences in RxSwift
- 普通數據流調用 publish 操作符后變為可連接數據流。
- 可連接數據流調用 connect 操作符后變為熱數據流。熱數據流可以在所有訂閱者中共享所發布的數據。
- 可連接數據流調用 refCount 操作符后具有引用計數功能,訂閱數從0到1時自動連接變為熱數據流,從1到0時自動斷開連接重新變回可連接數據流。
- 可連接數據流或熱數據流調用 replay 操作符后具有緩存功能,能緩存一部分或全部所發布的數據,新的訂閱者在訂閱時能夠接收到訂閱之前緩沖區的數據。



share, replay, share(replay:scope:)
RxSwift: share vs replay vs shareReplay
Understanding the RxSwift share operator
RxSwift: share()-ing is Caring
- share 相當于 publish + refCount,有引用計數功能,訂閱數從0到1時自動連接,從1到0時自動斷開連接。
- replay 沒有引用計數功能,需要調用 connect 之后才能連接。
- replay 有緩存功能,可以指定緩存的大小。
- share(replay:scope:) 相當于 share + replay,同時具有引用計數功能和緩存功能。
scope = .whileConnected 只有在連接時才緩存數據,斷開連接時緩存被釋放,重新連接后新的訂閱者不會接收到訂閱之前發布的數據。
scope = .forever 即使斷開連接時緩存仍然保持,重新連接后新的訂閱者會接收到訂閱之前發布的數據。
Driver
Driver 是 RxCocoa 中的一個 Trait,即具有某些特性的數據流。
Driver 數據流的特性
- 不會出錯
- 在主線程觀察數據
- 共享副作用
share(replay: 1, scope: .whileConnected)
示例
let results = query.rx.text
.throttle(.milliseconds(300), scheduler: MainScheduler.instance)
.flatMapLatest { query in
fetchAutoCompleteItems(query)
.observeOn(MainScheduler.instance) // results are returned on MainScheduler
.catchErrorJustReturn([]) // in the worst case, errors are handled
}
.share(replay: 1) // HTTP requests are shared and results replayed
// to all UI elements
results
.map { "\($0.count)" }
.bind(to: resultCount.rx.text)
.disposed(by: disposeBag)
results
.bind(to: resultsTableView.rx.items(cellIdentifier: "Cell")) { (_, result, cell) in
cell.textLabel?.text = "\(result)"
}
.disposed(by: disposeBag)
這段代碼的功能為發出 http 請求,將結果數據與兩個控件綁定
- .observeOn(MainScheduler.instance)
在主線程中監聽數據, - .catchErrorJustReturn([])
出錯時返回空數組 - .share(replay: 1)
結果數據需要與兩個控件綁定,必須使用熱數據流來共享數據。如果使用冷數據流來綁定兩個控件將導致發送兩次 http 請求
let results = query.rx.text.asDriver() // This converts a normal sequence into a `Driver` sequence.
.throttle(.milliseconds(300), scheduler: MainScheduler.instance)
.flatMapLatest { query in
fetchAutoCompleteItems(query)
.asDriver(onErrorJustReturn: []) // Builder just needs info about what to return in case of error.
}
results
.map { "\($0.count)" }
.drive(resultCount.rx.text) // If there is a `drive` method available instead of `bind(to:)`,
.disposed(by: disposeBag) // that means that the compiler has proven that all properties
// are satisfied.
results
.drive(resultsTableView.rx.items(cellIdentifier: "Cell")) { (_, result, cell) in
cell.textLabel?.text = "\(result)"
}
.disposed(by: disposeBag)
這段代碼改用 Driver 來完成同樣的功能。
- .asDriver()
將數據流轉換為 Driver 數據流,后者是一種共享數據流,具有共享數據的功能 - .asDriver(onErrorJustReturn: [])
出錯時返回空數組,Driver 數據流能在主線程中監聽數據, - .drive(resultCount.rx.text)
Driver 必須使用 drive 方法來綁定控件
Signal
Signal 是 RxCocoa 中的一個 Trait,即具有某些特性的數據流。
Signal 數據流的特性
- 不會出錯
- 在主線程觀察數據
- 共享計算資源
share(scope: .whileConnected) - 沒有緩存,新的訂閱者不會接收訂閱之前所發布的數據
浙公網安備 33010602011771號