我如何制作一个可重置的RxSwift计时器?

问题描述 投票:2回答:1

我正在尝试构建一个倒数计时器应用。自然,我需要一个Observable<Int>序列,该序列每秒给我一个元素。所不同的是,我需要此序列来响应其他两个序列的更改:

  • 已暂停:Observable<Bool>。这会模拟用户按下暂停/继续按钮]
  • 重置:Observable<Void>。这样可以模拟用户按下“重置”按钮。

重置按钮会将计时器重置为其初始值(resetState),并同时暂停计时器

用户可以随时按下重置按钮:

  1. 未启动计时器时重置
  2. 计时器运行时重置,未暂停,未结束
  3. 暂停计时器时重置,未结束
  4. 计时器结束后重置

this questionthis question的答案结合在一起,我得以提出一个Timer类,如下所示:

class Timer {
    var paused = true
    {
        didSet {
            rxPaused.accept(paused)
        }
    }
    var ended = false

    let rxPaused = BehaviorRelay(value: true)
    let disposeBag = DisposeBag()

    // timerEvents is the observable that client code should subscribe to
    var timerEvents: Observable<Int>!

    var currentState: Int
    let resetState: Int

    init(resetState: Int) {
        self.currentState = resetState
        self.resetState = resetState
        reset()
    }

    func start() {
        if !ended {
            paused = false
        }
    }

    func pause() {
        paused = true
    }

    func reset() {
        ended = false
        currentState = resetState
        pause()
        timerEvents = rxPaused.asObservable()
            .flatMapLatest {  isRunning in
                isRunning ? .empty() : Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
            }
            .enumerated().flatMap { (index, int) in Observable.just(index) }
        .map { [weak self] x in (self?.resetState ?? x) - x }
            .take(self.resetState)
        timerEvents.subscribe(onNext: { [weak self]
            timerEvent in
            self?.currentState -= 1
            }, onCompleted: {
                [weak self] in
                self?.ended = true
        }).disposed(by: disposeBag)
    }
}

用法:

let timer = Timer(resetState: 20)
timer.timerEvents.subscribe(
    onNext: { [unowned self] (timerEvent) in
        print(timerEvent.state)
        self.updateTimerLabelText()
}).disposed(by: disposeBag)

这仅在上述情况4中按预期工作。

如果您尝试在结束之前重置此计时器,事情会变得很有趣。例如,在情况1(甚至在启动之前复位)中,timerEvents每秒钟产生两个相同的元素。这不仅是错误的,而且还会导致currentState的下降速度快两倍。我怀疑这是因为timerEvents在其之前的值完成之前被分配了第二次,但是我认为没有办法“完成”一个未完成的可观察对象,是吗?

而且我什至不敢说出情况2和3会发生什么。

如何使此重置计时器起作用?

我正在尝试构建一个倒数计时器应用。自然,我需要一个Observable 序列,该序列每秒为我提供一个元素。扭曲之处在于我需要此序列来响应对两个...的更改...

swift timer rx-swift
1个回答
1
投票

更新

© www.soinside.com 2019 - 2024. All rights reserved.