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 不在后台状态下工作的主要内容,如果未能解决你的问题,请参考以下文章

rxjs创建异步数据的Observable

如何在基础活动暂停时暂停rxjava Observable.interval

杀死一个 Observable

rxjs——subject和Observable的区别

Rxjs 如何知道 observable 有多少订阅者?

ReactiveProperty初始值