Rx flatMapLatest 没有通过完成?

Rx flatMapLatest doesn't pass completed through?

我希望在看到 running -> Event completed 后立即看到 timer -> Event completed 输出,但它没有发生。

有人可以解释原因并给我一些关于如何完成 timer 可观察对象的想法吗?

/// playground

import RxSwift
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true


struct TimerCountdown {

    let timer: Observable<Int>

    init(running: Observable<Bool>) {
        timer = running.flatMapLatest { [=10=] ? Observable<Int>.interval(1.0, scheduler: MainScheduler.instance) : Observable<Int>.never() }
    }

}

let running = PublishSubject<Bool>()
let countdown = TimerCountdown(running: running)

_ = running.debug("running").subscribe()

_ = countdown.timer.debug("timer").subscribe()

running.onNext(true)
DispatchQueue.main.asyncAfter(deadline: .now() + 3.5) {
    running.onNext(false)
}

DispatchQueue.main.asyncAfter(deadline: .now() + 7.5) {
    running.onNext(true)
}

DispatchQueue.main.asyncAfter(deadline: .now() + 10.5) {
    running.onCompleted()
}

这是我找到的解决方案:

struct TimerCountdown {

    let timer: Observable<Int>

    init(running: Observable<Bool>) {
        timer = running
            .flatMapLatest { [=10=] ? Observable<Int>.interval(1.0, scheduler: MainScheduler.instance) : Observable<Int>.never() }
            .takeUntil(running.materialize().filter { [=10=].isCompleted })
    }
}

这是另一个不需要订阅 running 两次的答案:

struct TimerCountdown {

    let timer: Observable<Int>

    init(running: Observable<Bool>) {
        timer = running.materialize()
            .flatMapLatest { (event) -> Observable<Int> in
                switch event {
                case let .next(value):
                    return value ? Observable<Int>.interval(1.0, scheduler: MainScheduler.instance) : Observable.never()
                case .completed:
                    return Observable.empty()
                case let .error(error):
                    return Observable.error(error)
                }
        }
    }
}