Background fetch triggered by remote notification does not work when woken from “Not running” state

Hello.

Our app fetches new contents using NSURLSession when the app receive silent push notification in background.

Receiving notification in “Suspended” state (the app remains in memory) it works perfectly. In “Not running” state, the system wakes the app in the background and the app can send request via NSURLSessionDataTask but completion handler of data task is not called.


func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
    let request: NSURLRequest = ...
    let task: NSURLSessionDataTask = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
        // This closure is not called when the app is woken from "Not Running". 
        let localNotification: UILocalNotification = UILocalNotification()
        localNotification.alertBody = "task completed"
        localNotification.soundName = UILocalNotificationDefaultSoundName
        application.presentLocalNotificationNow(localNotification)
        completionHandler(UIBackgroundFetchResult.NewData)
    })
    task.resume()
}


The reference says "the system does not automatically launch your app if the user has force-quit it". We have the issue though the user does not force quit the app. Could anyone help us?


Thanks.

Accepted Reply

Huh? You’re issuing the request in the NSURLSession shared session. Such requests will only run as long as the app remains running. If the app is suspended again, which is typically what happens in this case, the request will stop halfway through.

You have two options here:

  • Continue using the shared session and use a UIApplication background task to prevent your app from suspended.

    IMPORTANT For this to work the request must completely quickly, because the UIApplication background task will typically only give you about 30 seconds of execution time.

  • Run the request in an NSURLSession background session, which will organise to resume your app when the request is complete.

If you choose the latter option, make sure you read the following:

Share and Enjoy

Quinn "The Eskimo!"
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

DTS will close for the winter holidays at the end of business on Wed, 23 Dec 2015 and re-open on Mon, 4 Jan 2016.

Replies

Force quit, refers to the state in which the user has removed the app from the recent apps

pane. This effectively force quits the app because no instance of the app is currently in memory.

There is no way around this unless your app makes use of specific background services to keep

it alive.

Huh? You’re issuing the request in the NSURLSession shared session. Such requests will only run as long as the app remains running. If the app is suspended again, which is typically what happens in this case, the request will stop halfway through.

You have two options here:

  • Continue using the shared session and use a UIApplication background task to prevent your app from suspended.

    IMPORTANT For this to work the request must completely quickly, because the UIApplication background task will typically only give you about 30 seconds of execution time.

  • Run the request in an NSURLSession background session, which will organise to resume your app when the request is complete.

If you choose the latter option, make sure you read the following:

Share and Enjoy

Quinn "The Eskimo!"
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

DTS will close for the winter holidays at the end of business on Wed, 23 Dec 2015 and re-open on Mon, 4 Jan 2016.