Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Countdown timer, that continue running in background

I need to create timer, that will continue running in background state and will update UI after app will enter foreground state. Most appropriative example for this is QuizClash app: enter image description here

I have 2 ideas below:

  1. beginbackgroundTaskWithExpirationHandler

    • Create first timer (30 sec interval, non-repeatable)
    • Create second timer (0.01 sec interval, repeatable)
    • First timer will fire [self timeExiped] method, which will show some UI updates
    • Second timer will fire update of ProgressBar on the picture above
    • Wrap it all in beginbackgroundTaskWithExpirationHandler method

    Doubts: if main timer will expired in background state, UI updates won't be shown(?)

  2. State restoring

    • Start the same timers
    • Use encode​Restorable​State​With​Coder:​​ to save current timestamp, when entering background
    • Use decode​Restorable​State​With​Coder:​​ to get difference between saved timestamp and now.
    • Invalidate main timer
    • Start new main timer with (remains_seconds - time_difference_seconds)

    Doubts: is it even a viable option, since i have no experience with it and can't try it out for a moment?

If you have any other idea, or can point me out at 2 described above, i'll put a beer, if you ever in Moscow :)

like image 580
Artem Zaytsev Avatar asked May 22 '26 04:05

Artem Zaytsev


2 Answers

What is the purpose of the Timer?

If it is to trigger UI changes, there is no point in trying to get it to "run in the background" because there's no UI to update.

With any approach, you will almost certainly want to use timestamps... when the app is returning to the foreground, get the elapsed time since the last timestamp, update your UI as needed, and restart a Timer for foreground activity / updates.

like image 189
DonMag Avatar answered May 24 '26 17:05

DonMag


Add an observer for UIApplicationDidBecomeActive to the ViewController containing the ProgressBar in viewWillAppear:

NotificationCenter.default.addObserver(forName: NSNotification.Name.UIApplicationDidBecomeActive, object: nil, queue: nil, using: self.applicationBecameActive)

Put it in viewWillAppear because the applicationBecameActive function should only fire when the viewcontroller containing the progress bar is on the top of the stack when the application becomes active again.

Then in the applicationBecameActive method, determine what the current progress value of the ProgressBar should be, update accordingly, and restart the ProgressBar progressing.

func applicationBecameActive(notification: Notification){

    //determine where the ProgressBar should be

    //set the ProgressBar progress value

    //restart the ProgressBar progress value updating

}

Don't forget to remove the observer on viewWillDissappear:

NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIApplicationDidBecomeActive, object: nil)
like image 26
JB288 Avatar answered May 24 '26 16:05

JB288



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!