can't start beginBackgroundTask swift 3

Alex picture Alex · Oct 4, 2017 · Viewed 7.3k times · Source

Sorry I am stuck, but I am trying to start background task (XCode8, swift 3)

Example from here: https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html#//apple_ref/doc/uid/TP40007072-CH4-SW3

In AppDelegate.swift:

func applicationDidEnterBackground(_ application: UIApplication) {
    var bgTask: UIBackgroundTaskIdentifier = 0;
    bgTask = application.beginBackgroundTask(withName:"MyBackgroundTask", expirationHandler: {() -> Void in
        print("The task has started")
        application.endBackgroundTask(bgTask)
        bgTask = UIBackgroundTaskInvalid
    })
}

The app has never shown "The task has started" message. What am I doing wrong?

Answer

rmaddy picture rmaddy · Oct 4, 2017

Your use of the background task is all wrong.

Waiting for the expiration handler to be called to call endBackgroundTask is poor practice and makes your app waste more resources than it needs. You should tell iOS immediately when your background task is complete.

So you should do something like:

func applicationDidEnterBackground(_ application: UIApplication) {
    var finished = false
    var bgTask: UIBackgroundTaskIdentifier = 0;
    bgTask = application.beginBackgroundTask(withName:"MyBackgroundTask", expirationHandler: {() -> Void in
        // Time is up.
        if bgTask != UIBackgroundTaskInvalid {
            // Do something to stop our background task or the app will be killed
            finished = true
        }
    })

    // Perform your background task here
    print("The task has started")
    while !finished {
        print("Not finished")
        // when done, set finished to true
        // If that doesn't happen in time, the expiration handler will do it for us
    }

    // Indicate that it is complete
    application.endBackgroundTask(bgTask)
    bgTask = UIBackgroundTaskInvalid
}

Also note that you should use beginBackgroundTask/endBackgroundTask around any code in any class that you want to keep running for a short period time even if the app goes into the background.

In this setup if the task isn't finished while the while loop is still working then the expirationHandler is called in parallel on a different thread. You should use the handler to stop your code and allow it to reach the application.endBackgroundTask(bgTask) line.