0

I am trying to execute a simple function that runs a Timer in the background of the app.

In short,

  1. A 10 second Timer starts as soon as app begins
  2. I lock the device after seeing confirmation the Timer has begun in the Foreground
  3. 10 seconds later, with the app in the Background, I should expect a log to appear. This currently works in the simulator but not on the device

Full code below. You can also download the app itself to try.

After consulting popular answers such as this (which also contains conflicting answers about whether a Timer actually runs in the background or not), I am not exactly what the authoritative answer is on at the topic.

Any help is appreciated.

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        var timer : Timer?
        if timer == nil {
            NSLog("Timer started")
            timer = Timer.scheduledTimer(withTimeInterval: 10, repeats: true, block: {_ in NSLog("After 10 seconds show up") //this will not work on a device
                //Also, I get the error: Can't end BackgroundTask: no background task exists with identifier 1 (0x1), or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.
            })
        }
    }
}
daspianist
  • 5,336
  • 8
  • 50
  • 94
  • This is the same question you asked before, in another form. The correct procedure is _not_ to abandon the earlier question and ask it again. You should _edit_ the previous question to get "better" answers if that's the issue. – matt Apr 05 '20 at 19:44

1 Answers1

0

It may be confusing, but questions like that actually do answer the question. Bottom line, the app is completely suspended (including timers) when the app enters the background. You can, however, request a little time before it is suspended as outlined in Extending Your App’s Background Execution Time. You’ll see many online references to this being able to allow an extra three minutes of background execution before it is suspended, but in iOS 13 this has been further reduced down to only 30 seconds.

Now, apps that have legitimate need or background execution (e.g. a navigation app, a VOIP app, a music playing app, etc.) can request special background execution modes (see About the Background Execution Sequence, but none of these are intended solely for the purpose of keeping a timer running in the background.

If you want to notify a user at some designated time in the future, use user notification service. But do not just attempt to keep your app running in the background.


By the way, while that link describes the process, their code snippet is misleading. See https://stackoverflow.com/a/23831862/1271826 for a more contemporary rendition.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Thanks for this and for linking to the official docs. I am curious about apps like sleep trackers that enable alarms to run many hours after its set in the app and with the app in the Background - is this also using background execution? – daspianist Apr 05 '20 at 19:38
  • 1
    The thing is, we went all through how timers can work in the background, in the OP's earlier question https://stackoverflow.com/questions/60779133/how-to-call-a-function-when-the-app-is-inactive-e-g-playing-music-in-backgroun – matt Apr 05 '20 at 19:45
  • Hi Matt, thanks for chiming in here. What Rob mentioned: "app is completely suspended", and your answer, essentially, that it works in the background, are in conflict to each other. – daspianist Apr 05 '20 at 19:51
  • 2
    @daspianist - Open matt’s project and look at the “Signing & Capabilities” test. You see that his app has requested “Audio” background permission. That’s what keeps the app running in the background (which allows the timer to proceed). But that’s not a viable solution for an app to be distributed via the App Store (unless, of course, you are really distributing a music app). See [About the Background Execution Sequence](https://developer.apple.com/documentation/uikit/app_and_environment/scenes/preparing_your_ui_to_run_in_the_background/about_the_background_execution_sequence). – Rob Apr 05 '20 at 20:15