swift - 在后台安排计时器
问题描述
我正在开发一个具有非常重要的流动时刻的应用程序。在前台和后台每x秒保存一次数据。我知道计时器运行时间不长,所以我添加了:
- 进入后台的bg任务
- 每x小时唤醒一次暂停的应用程序
这是代码:
class BackgroundTimer {
private var bgTask: UIBackgroundTaskIdentifier = .invalid
private var timer: Timer?
private var wakeUpTimer: Timer?
init() {
addNotifications()
startTimer()
startWakeUpTimer()
}
// MARK: Notifications
private func addNotifications() {
removeNotifications()
NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(applicationDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
}
private func removeNotifications() {
NotificationCenter.default.removeObserver(self)
}
@objc private func applicationDidEnterBackground() {
stopBackgroundTask()
startBackgroundTask()
}
@objc private func applicationDidBecomeActive() {
stopBackgroundTask()
}
// MARK: Timer
public func startTimer() {
stopForegroundTask()
startForegroundTask()
}
private func fireTimer(_ timer: Timer) {
// Run code every 30 sec
// here
// -----------
stopBackgroundTask()
startBackgroundTask()
}
private func startForegroundTask() {
timer = Timer.scheduledTimer(withTimeInterval: 30, repeats: true, block: fireTimer)
}
private func stopForegroundTask() {
timer?.invalidate()
timer = nil
}
// MARK: Background task
private func startBackgroundTask() {
guard timer != nil else { return }
let state = UIApplication.shared.applicationState
guard ((state == .background || state == .inactive) && bgTask == .invalid) else { return
}
bgTask = UIApplication.shared.beginBackgroundTask(expirationHandler: { [weak self] in
self?.stopBackgroundTask()
})
}
private func stopBackgroundTask() {
guard bgTask != .invalid else { return }
UIApplication.shared.endBackgroundTask(bgTask)
bgTask = .invalid
}
// MARK: Wake up timer
private func startWakeUpTimer() {
let date = Date().addingTimeInterval(4 * 3600)
let timer = Timer(fireAt: date, interval: 0, target: self, selector: #selector(fireWakeUpTimer), userInfo: nil, repeats: false)
RunLoop.main.add(timer, forMode: .common)
}
@objc private func fireWakeUpTimer(_ timer: Timer) {
startWakeUpTimer()
}
}
但是,像往常一样,有些东西效果不佳。定时器可以停止或唤醒定时器没有启动。你有同样的经历吗?如何改进功能?
解决方案
推荐阅读
- javascript - 如何为每个配对号码添加一些文本
- java - 将 @Primary 与 spring-context-indexer 一起使用
- git - .gitattributes 中的“* text=auto eol=lf”和“* text eol=lf”有什么区别?
- node.js - 在 mongodb 中阅读然后更新的最佳方法是什么?
- java - Whatsapp 意图
- javascript - 自定义 http 标头破坏了 CORS
- javascript - JS 控制台变量输出问题
- android-studio - OnClickerListener 问题,可以在模拟器中打开应用
- amazon-web-services - 一次提交的 AWS CodePipeline 双重执行
- c# - 减少重复 - 从实例方法创建委托