iOS NSURLSession Setting up background configuration


To create a background session

 // Swift:
 let mySessionID = "com.example.bgSession"
 let bgSessionConfig = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(mySessionID)
 let session = NSURLSession(configuration: bgSessionConfig)
 // add tasks here

 // Objective-C:
 NSString *mySessionID = @"com.example.bgSession";
 NSURLSessionConfiguration *configuration =
     [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: mySessionID];
 NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration

Additionally, in iOS, you must set up support for handling background app relaunch. When your app's application:handleEventsForBackgroundURLSession:completionHandler: method (Objective-C) or application(_:handleEventsForBackgroundURLSession:completionHandler:) method (Swift) gets called, it means your app has been relaunched in the background to handle activity on a session.

In that method, you should create a new session with the provided identifier and configure it with a delegate to handle events just like you normally would in the foreground. Additionally, you should store the provided completion handler in a dictionary, using the session as the key.

When the delegate's URLSessionDidFinishEventsForBackgroundURLSession: (Obj-C) / URLSessionDidFinishEventsForBackgroundURLSession (Swift) method gets called to tell you that there are no more events to handle, your app should look up the completion handler for that session, remove the session from the dictionary, and call the completion handler, thus telling the operating system that you no longer have any outstanding processing related to the session. (If you are still doing something for some reason when you get that delegate call, wait until done.) As soon as you call that method, the background session immediately gets invalidated.

If your application then receives an application:application:didFinishLaunchingWithOptions: call (likely indicating that the user foregrounded your app while you were busy processing background events), it is safe to create a background session with that same identifier, because the old session with that identifier no longer exists.

If you're curious about the details, at a high level, when you create a background session, you're doing two things:

  • Creating a session in an external daemon (nsurlsessiond) to handle the downloads
  • Creating a session within your app that talks to that external daemon via NSXPC

Normally, it is dangerous to create two sessions with the same session ID in a single launch of the app, because they both are trying to talk to the same session in the background daemon. This is why the official documentation says to never create multiple sessions with the same identifier. However, if the first session was a temporary session created as part of a handleEventsForBackgroundURLSession call, the association between the now-invalidated in-app session and the session in the background daemon no longer exists.