How to setup long running timers on iOS

77 Views Asked by At

I want to create a timer that should fire every hour. But from my research, an app gets suspended after 10 mins in the background. It also seems like the app gets suspended after the screen is locked.

I want to trigger this timer every 1 hour. I will be invalidating the timer when app goes in the background and restart it when the app foregrounds. So I have a few questions:

  1. When the user backgrounds the app and comes back to it, will the timer fire immediately if it has been 1+ hour?
  2. What happens if the user returns to the app after multiple (2+) hours, will the timer fire multiple times?

Are there any recommended ways to setup such longer running timers so they fire more consistently and not just once when they were setup?

1

There are 1 best solutions below

0
Chetan Lodhi On

You can do something like this without using background timer. It is only idea how you can achieve your requirement, add one or more hours condition as per your requirement.

var totalTime = Double()

override func viewDidLoad() {
  super.viewDidLoad()

// MARK: - To Reset timer's sec if app is in background and foreground
    NotificationCenter.default.addObserver(self, selector: #selector(self.background(_:)), name: UIApplication.didEnterBackgroundNotification, object: nil)

    NotificationCenter.default.addObserver(self, selector: #selector(self.foreground(_:)), name: UIApplication.willEnterForegroundNotification, object: nil)
}

 @objc func background(_ notification: Notification) {
   if self.totalTime > 0{
     user_default.setValue(self.totalTime, forKey: "TotalSecInBackground")
     user_default.setValue(Date().timeIntervalSince1970, forKey: "OldTimeStamp")
     LogInfo("total seconds left in background: \(self.totalTime)")
  }
}

  @objc func foreground(_ notification: Notification) {
   let timerValue: TimeInterval = user_default.value(forKey: "TotalSecInBackground") as? TimeInterval ?? 0
   let otpTimeStamp = user_default.value(forKey: "OldTimeStamp") as? TimeInterval ?? 0
   let timeDiff = Date().timeIntervalSince1970 - otpTimeStamp
    if timerValue > timeDiff{
    LogInfo("total second & timeDiff:, \(Int(timerValue)),\(Int(timeDiff))")
    let timeLeft = timerValue - timeDiff
    self.totalTime = Int(timeLeft)
    LogInfo("timeLeft: \(Int(timeLeft))") // <- This is what you need
}}