如何在主线程中执行 do 运算符的 onSubscribe 操作

How do I execute onSubscribe action of do operator in Main thread

我在do运算符的onSubscribe动作中执行了UI相关操作。我得到一个

Main Thread Checker: UI API called on a background thread

Xcode 中的控制台错误。我尝试使用 observe(on: MainScheduler.instance) 但没有成功。

这是我的代码片段:

 checkCurrentNetworkAndConnect().observe(on: MainScheduler.instance).do(onSubscribe: {
      // UI related stuff
 })

我也试过 subscribe(on: MainScheduler.instance) 但没用。

我怎样才能做到这一点?

如果您在后台线程上调用 subscribe,就会发生这种情况。如果您在后台线程上调用订阅,那么 Observable 将在该后台线程上被订阅。要解决这个问题,您需要在 do 运算符 subscribe(on:) 之后使用 do...

像这样:

func example() {
    checkCurrentNetworkAndConnect()
        .do(onSubscribe: {
            print("UI related stuff")
        })
        .subscribe(on: MainScheduler.instance)
        .subscribe()
}

通过以上,即使你在后台线程调用example()onSubscribe:闭包也会在主线程上执行。

如果出于某种原因您还希望在后台线程上使用 checkCurrentNetworkAndConnect(),那么您可以在 do.

之上使用另一个 subscribe(on:) 来实现

综上所述,您首先不应该在 do(onSubscribe:) 中执行明显的副作用。将调试代码放在那里是一回事,但仅此而已。我已经使用 RxSwift 6 年了,我根本不需要使用 do(onSubscribe:) ,更不用说重要的代码了。可能有更好的方法来实现您要实现的最终目标。


回应您的评论。你如何着手做你想做的事情在很大程度上取决于未提供的细节。下面我做了一些简化的假设。如果您的问题有所不同,我建议您 post 提出一个新问题并提供详细信息...

func example(operations: [Observable<Void>], messages: [String], label: UILabel, disposeBag: DisposeBag) {
    Observable.concat(operations.enumerated().map { index, op in
        op.map { messages[index + 1] }
    })
        .startWith(messages[0])
        .observe(on: MainScheduler.instance)
        .bind(to: label.rx.text)
        .disposed(by: disposeBag)
}

以上代码假定:

  • 您有一组表示为可观察值的操作
  • 其中 none 需要先前操作提供的数据
  • 其中 none 发出您希望使用或保留的数据
  • 每个操作都有一条消息需要在操作开始前显示
  • 最后一个操作完成时会显示一条附加消息