delaySubscription 不适用于 rx_tap

delaySubscription doesn't work with rx_tap

这是我的代码的简短版本,可以重现问题:

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([=11=]) }
            .addDisposableTo(disposeBag)
    }
}

我希望 'delayed' 信号在我点击按钮 2 秒后触发,但运气不佳。实际发生了什么:我第一次点击按钮时,'source' 触发但没有其他任何反应。然后,当我再次点击时,'source' 和 'delayed' 同时触发。我认为这是一些线程问题,所以我尝试在各处添加 observeOn(MainScheduler.sharedInstance) 但它没有帮助。有什么想法吗?

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

为了回答我自己的问题,delaySubscription 似乎只适用于冷可观察量。

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

一个热观察对象,例如 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([=10=]) }
        .addDisposableTo(disposeBag)
    }
}