1

这是我的代码的简短版本,它将重现该问题:

import UIKit
import RxSwift
import RxCocoa

class ViewController: UIViewController {
    @IBOutlet weak var button: UIButton!

    let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        let source = button.rx_tap.map { _ in "source" }

        let delay = source.map { _ in "delayed" }
            .delaySubscription(2.0, MainScheduler.sharedInstance)

        [source, delay].toObservable().merge()
            .subscribeNext { print($0) }
            .addDisposableTo(disposeBag)
    }
}

我希望“延迟”信号在我点击按钮后 2 秒触发,但没有这样的运气。实际发生的情况:我第一次点击按钮时,“源”会触发,但没有其他任何反应。然后当我再次点击时,“源”和“延迟”同时开火。我认为这是一些线程问题,所以我尝试observeOn(MainScheduler.sharedInstance)在任何地方添加,但没有帮助。有任何想法吗?

更新:通过添加.debug()到流中,我发现延迟的流实际上在 2 秒后订阅了源。但这仍然不能解释为什么它也不会在 2 秒后触发通知。

4

1 回答 1

4

要回答我自己的问题,它似乎delaySubscription只适用于冷观测值。

一个冷的 observable,例如 a timer,只有在它被订阅时才开始触发通知,并且订阅它的每个人都会得到一个新的序列。这就是为什么简单地延迟对冷的 observable 的订阅也会延迟所有的通知。

一个热的可观察对象,例如一个 UI 事件,与它的所有订阅者共享相同的序列,因此延迟订阅绝对不会影响它的通知。

相反,我可以使用flatMap运算符将​​每个源通知转换为另一个可观察对象,该可观察对象在一定延迟后触发其唯一通知,并合并这些可观察对象的结果:

class ViewController: UIViewController {
@IBOutlet weak var button: UIButton!

let disposeBag = DisposeBag()

override func viewDidLoad() {
    super.viewDidLoad()

    let source = button.rx_tap.map { _ in "source" }

    let delayed = source.flatMap { _ in
        timer(1.0, MainScheduler.sharedInstance)
            .map { _ in "delayed" }
    }

    [source, delayed]
        .toObservable().merge()
        .subscribeNext { print($0) }
        .addDisposableTo(disposeBag)
    }
}
于 2016-01-03T08:52:13.917 回答