我如何制作一个可重置的RxSwift计时器?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我如何制作一个可重置的RxSwift计时器?相关的知识,希望对你有一定的参考价值。
我正在尝试构建一个倒数计时器应用。自然,我需要一个Observable<Int>
序列,该序列每秒给我一个元素。所不同的是,我需要此序列来响应其他两个序列的更改:
- 已暂停:
Observable<Bool>
。这会模拟用户按下暂停/继续按钮] - 重置:
Observable<Void>
。这样可以模拟用户按下“重置”按钮。
重置按钮会将计时器重置为其初始值(resetState
),并同时暂停计时器。
用户可以随时按下重置按钮:
- 未启动计时器时重置
- 计时器运行时重置,未暂停,未结束
- 暂停计时器时重置,未结束
- 计时器结束后重置
将this question和this 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
答案
更新
以上是关于我如何制作一个可重置的RxSwift计时器?的主要内容,如果未能解决你的问题,请参考以下文章