Timer stops counting when screen blanks

I am new to Apple app development, so I am still learning.

My first application is a basic countdown timer.

Xcode 14.2 and Swift / UIKit Target iPhone 15.0 and higher

My goal is the timer will count down and alert the user with a tone/vibrate when it reaches zero.

Currently I have a working app but have two challenges:

  1. When the iPhone screen blanks, my timer stops counting down. What is the best dev approach to keep the timer counting in the background even if the screen blanks or device locks?

  2. If I can solve #1, then I will have a second challenge to sound an alarm tone/vibrate if the counter reaches zero while the screen is blank or device is locked.

Here is the code I am using to trigger the timer:

    @IBAction func clickStartPauseButton(_ sender: Any) {         { timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true) ... }

And this code is doing the work to increment my counter variable:

    @objc func timerAction() {         if (counter > 0) {         counter = counter - 1         } else {             timer.invalidate()         }     }

Thank you for any assistance or direction. A resource with some sample code would be much appreciated.

Replies

When the iPhone screen blanks

Its sounds like the device is locking the screen, either because the user pressed the Sleep/Wake button or because of the idle timer.

If so, this behaviour is expected. When the screen locks your app is pushed the background. Unless there’s something keeping your app running, it’ll shortly thereafter be suspended by the system, that is, all threads in your process will stop running. And unless there’s something keeping the system running — like the Music app playing — the device itself will go to sleep, that is, the application process will stop.

You have two options here:

  • If your users wants your countdown timer to be on screen at all times — I could imagine this would make sense is some ‘mission critical’ situations — you can disable the idle timer. See the idleTimerDisabled property.

  • In most cases, and this is what the Apple timer does [1], you will want to allow the app to suspend and then use a local notification to notify the user when the timer fires.

For more background (cough) on this, see the various links in the Background Tasks Resources post.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] More or less (-:

Thank you for the info and direction. My first iteration to achieve the behavior I wanted for my app was to set the idleTimerDisabled property from the UIApplication class. By adding this statement

            UIApplication.shared.isIdleTimerDisabled = true (or false)

I added this line of code after tapping my countdown START (= true) and when the STOP, RESET, or app countdown reaches zero, I sit it back to the default (= false). And all is working fine now.

One follow up question, what happens to the isIdleTimerDisabled property value when the user cancels the application by swiping it up? After doing some testing it seems the system resets back to the default (false) setting. I am not sure if their is a way to identify when a user cancels an app this way and to reset the value before the application is totally terminated.

I my intention is to further refactor my code and attempt your second recommendation to allow the app to suspend and then use a local notification to possibly calculate the time that has past using system date info and the display the countdown timer when the user taps the screen/reactivates the app. When I figure that out I should also be able to to notify the user when the timer reaches zero and I want an audible alert or vibration.

Thanks again for your assistance... I have a lot to learn.

what happens to the isIdleTimerDisabled property value when the user cancels the application by swiping it up?

The system ignores the value of this property if your app is not at the front. There are two swipe up gestures that might be in play here:

  • A standard swipe up is equivalent to pressing the Home button. It moves your app to the background. You can learn about this by watching for the .didEnterBackgroundNotification notification.

  • Swiping up from the multitasking UI terminates your app and prevents it from running again until the user manually launches it. If your app is in the foreground, this will likely generate a .willTerminateNotification notification.

In both cases the app is no longer in the foreground and thus the value in isIdleTimerDisabled is irrelevant.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"