`.drive()` 和 `.bind(to:)` 之间的区别

Difference between `.drive()` and `.bind(to:)`

我现在正在学习 RxSwift。

你什么时候用.drive(something),什么时候用.bind(to: something)

示例:

let disposeBag = DisposeBag()
let isEnabled = BehaviorRelay(value: true)
let button = UIButton()
// what is the benefit of this:
isEnabled.asDriver().drive(button.rx.isEnabled).disposed(by: disposeBag)
// over this:
isEnabled.bind(to: button.rx.isEnabled).disposed(by: disposeBag)
// or is the above better?

中的答案并没有多大帮助。我不明白为什么甚至需要添加 asDriver() 才能使其成为不会失败的东西。

来自 RxSwift 的 GitHub 页面

This is the most elaborate trait. Its intention is to provide an intuitive way to write reactive code in the UI layer, or for any case where you want to model a stream of data Driving your application.

  1. 不能出错。
  2. 观察发生在主调度程序上。
  3. 分享方 效果(分享(重播:1,范围:.whileConnected))。

从同一页面再次复制

Its intended use case was to model sequences that drive your application.

现在回到分歧?

驱动程序确保观察仅发生在主线程上:

Drive 是 RxSwift 中的一个特性,它确保观察仅在 MainThread 上发生,这意味着无论在哪个线程上发出事件并触发驱动程序,驱动程序始终确保将事件转发给下一个操作员在链中或其在主线程上的订阅块。

在 Rx 中,所有事件都在事件发生的同一线程上传播。因此,如果您使用 subject.onNext( 在 say thread (100) 上触发一个主题,它的订阅块将在同一线程 (100) 上被调用,直到并且除非您使用 observedOnsubscribedOn 运算符确保手动线程切换。

如果您从 viewModel 中的 observables/subjects 驱动 UI 组件,驱动程序非常有意义。假设您在后台线程上调用 API 从服务器获取数据,您不想在后台线程上访问您的 UI 组件,connecting/converting 您的 observables/subjects 到驱动程序(使用asDriver 并传递 onErrorJustReturn) 并通过驱动程序驱动您的 UI 组件将确保您的 UI 组件始终在主线程

上访问

不能出错

通常当发生错误时,订阅将被终止,如果您正在驱动 UI 组件,您不希望 subscription/bind 每次出现错误事件时都中断。

示例:假设您通过 CoreData 驱动您的 tableView,并且由于某种原因从 CoreData 获取数据时发生错误,如果您不使用驱动器并且使用了平面 bind(to:它的 onError 将被触发,它与 UI 组件的绑定将被破坏。如果再次获取数据,则必须重新建立此绑定。对于 UI 获取/获取数据时的组件错误应该没有任何区别。它应该只是一个改变其状态的事件流。

bindTo 只不过是 subscribe 上的语法糖衣,所以如果你使用 bindTosubscribe 来驱动UI 个组件,您将失去 drive 固有地给 table 带来的所有好处。

您始终可以使用 observedOn 来确保手动将线程切换到 main,并且还可能有一些重试机制来在发生错误时建立订阅/保留订阅,但最终您将结束写你自己的驾驶特质

什么时候用drive,什么时候用bindTo

拇指规则是您是否尝试驱动 UI 组件使用 drive 否则使用 bindTo。一般来说,如果你希望你的订阅只发生在主线程上并且不希望你的订阅出错(比如驱动 UI 组件)使用 driver 否则坚持使用 bindTosubscribe

编辑 1:

OP在评论中的问题:

asDriver() in my example makes sure isEnabled is being observed on the main thread and I don’t have to pass onErrorJustReturn because BehaviorRelay also can’t fail? In this case drive() has the main thread benefit but not the failsafe benefit?

在我的示例中确保在主线程上观察到 isEnabled - YES

我不用传onErrorJustReturn因为BehaviorRelay也不会失败? - 宾果

如果你更深入地检查 BehaviorRelay,你会发现

/// BehaviorRelay is a wrapper for BehaviorSubject. /// /// UnlikeBehaviorSubject it can't terminate with error or completed.

很明显,BehaviorRelay 不会出错,因此编译器足够智能,可以理解而不是要求 onErrorJustReturn。如果你真的想看到一个使用 BehaviorSubject 并且编译器会要求它:)

感谢 Daniel 指出我的错误,驱动力并不是确保观察仅发生在 MainThread 上的唯一特征,因此编辑了我的答案以反映相同的情况。谢谢