Observable.interval 不在后台状态下工作
Posted
技术标签:
【中文标题】Observable.interval 不在后台状态下工作【英文标题】:Observable.interval not working in background state 【发布时间】:2020-06-03 10:59:30 【问题描述】:我正在尝试使用 RxSwift 创建一个简单的计时器,我的灵感来自这个答案 ()。当应用程序在前台时它工作正常。问题是,如果应用程序状态进入后台,它会停止,然后如果应用程序状态再次进入前台,则从它停留的位置开始计数。
https://***.com/a/41198811/3950721
快速浏览; Simple Timer with RxSwift
【问题讨论】:
【参考方案1】:您遇到的是标准和预期的行为。当应用程序进入后台时,所有计时器和其他后台任务(无论是否在 Rx 中)都会停止。
为了让任何人帮助您,您需要解释您正在尝试做什么,以便我们可以想出另一种方法来做。
例如,在我的一个应用程序中,用户应该在 5 分钟不活动后退出,所以我有这个来确保它发生:
let idleTime = 5 * 60
let foregroundTimerTripped = Observable.merge(
application.rx.methodInvoked(#selector(UIApplication.sendEvent(_:))).map(to: ()),
rx.methodInvoked(#selector(UIApplicationDelegate.applicationWillEnterForeground(_:))).map(to: ())
)
.debounce(.seconds(idleTime), scheduler: MainScheduler.instance)
let backgroundTime = rx.methodInvoked(#selector(UIApplicationDelegate.applicationDidEnterBackground(_:)))
.map(to: ())
.flatMap Observable.just(Date())
let foregroundTime = rx.methodInvoked(#selector(UIApplicationDelegate.applicationWillEnterForeground(_:)))
.map(to: ())
.flatMap Observable.just(Date())
let backgroundTimerTripped = foregroundTime
.withLatestFrom(backgroundTime) $0.timeIntervalSince($1)
.filter $0 > TimeInterval(idleTime)
.withLatestFrom(bearer)
let timeToLogout = Observable.merge(foregroundTimerTripped, backgroundTimerTripped)
【讨论】:
丹尼尔,谢谢。我将使用它来输入一次密码的页面。计时器显示 OTP 到期前的剩余秒数。我通过保持到期日期解决了我的问题。新计时器每秒计算到期日期的剩余时间。【参考方案2】:除了Daniel的回答,如果你和我的有类似的问题(像一次性密码屏幕一样过期的定时器),这里是我的解决方案;
感谢过期日期,只要计时器运行,它就会发出剩余的秒数到过期日期。由于过期日期是恒定的,剩余的秒数不受应用程序状态的影响。
let expireDate = Date().addingTimeInterval(TimeInterval(seconds))
timerBag = DisposeBag() // to release timer.
Observable<Int>
.interval(.seconds(1), scheduler: MainScheduler.instance)
.map _ in expireDate
.compactMap( expireDate -> Int? in
let calendar = Calendar.current
let components = calendar.dateComponents([.second], from: Date(), to: expireDate)
return components.second
.subscribe(onNext: [weak self] remainingSecondsToExpire in
print(remainingSecondsToExpire)
).disposed(by: timerBag!)
【讨论】:
以上是关于Observable.interval 不在后台状态下工作的主要内容,如果未能解决你的问题,请参考以下文章