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

Posted

技术标签:

【中文标题】如何在主线程中执行 do 运算符的 onSubscribe 操作【英文标题】:How do I execute onSubscribe action of do operator in Main thread 【发布时间】:2021-11-09 17:10:28 【问题描述】:

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

主线程检查器:在后台线程上调用的 UI API

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

这是我的sn-p:

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

我也尝试了subscribe(on: MainScheduler.instance),但不起作用。

我怎样才能做到这一点?

【问题讨论】:

这里的问题是你试图在do操作符的onSubscribe中做一个UI相关的操作。这是个错误。告诉我们更多关于您为什么要这样做的信息,也许我们可以向您展示完成任务的更好方法。 感谢@DanielT。我想要实现的是在checkCurrentNetworkAndConnect 操作有效启动时更新标签文本 【参考方案1】:

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

类似这样的:

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:),更不用说重要的代码了。可能有更好的方法来实现您想要实现的最终目标。


回应您的评论。你如何去做你想做的事很大程度上取决于未提供的细节。下面我做了一些简化的假设。如果您的问题不同,我建议您发布一个包含详细信息的新问题...

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)

上面的代码假设:

您有一组表示为可观察对象的操作 他们都不需要先前操作提供的数据 它们都不会发出您愿意使用或保留的数据 每个操作都有一条消息需要在操作开始前显示 最后一个操作完成时会显示一条附加消息

【讨论】:

感谢@Daniel T。我是 RxSwift 的新手(我只使用了一周),所以我借此机会向您解释我想要实现的目标。我必须一个接一个地执行一系列操作。当一个操作即将开始时,我想更新一个加载器标签来通知用户当前的操作。 我更新了答案。 嗨@Daniel T.,我在link 提出了另一个问题。我想让你看看。非常感谢您的帮助。

以上是关于如何在主线程中执行 do 运算符的 onSubscribe 操作的主要内容,如果未能解决你的问题,请参考以下文章

GCD - 如何在主线程上等待在主队列上执行的异步回调

iOS - 确保在主线程上执行[重复]

在后台线程执行硬任务,在主线程返回结果

如何在主线程上安全地使用[NSTask waitUntilExit]?

面试官:你说说如何让“线程”按序执行?

从并行线程在主 Maya 线程上执行代码