Create tasks that download files while your app is inactive.
For long-running and nonurgent transfers, you can create tasks that run in the background. These tasks continue to run even when your app is suspended, allowing your app to access the downloaded file when the app is resumed.
Configure the Background Session
Create a background URL session as follows. Listing 1 demonstrates this process.
Create a background
URLSessionobject with the class method
URLSession, providing a session identifier that is unique within your app. Because most apps need only a few background sessions (usually one), you can use a fixed string for the identifier, rather than a dynamically generated identifier. The identifier doesn’t need to be unique globally.
To have the system to wake up your app when a task completes and the app is in the background, make sure the
sessionproperty is set to
Sends Launch Events
For time-insensitive tasks, enable the
isproperty, so the system can wait for optimal conditions to perform the transfer, such as when the device is plugged in or connected to Wi-Fi.
URLSessioninstance to create a
URLSessioninstance. The session must provide a delegate, to receive events from the background transfer.
Create and Schedule the Download Task
You create download tasks from the session with either the
download method that takes a URL, or the
download method that takes a
URLRequest instance. You set properties on this method to help the system optimize its behavior.
Optionally, set the
earliestproperty to schedule the download to begin at some point in the future. The download isn’t guaranteed to begin at precisely this time, but it won’t start sooner.
To help the system efficiently schedule network activity, set the properties
Of Bytes Client Expects To Send
count. These values are best-guess upper bounds on the expected byte count, and should account for headers as well as body data.
Of Bytes Client Expects To Receive
To start the task, call
In Listing 2, the task is set to begin at least one hour in the future and is configured to send around 200 bytes of data and receive around 500 KB.
Handle App Suspension
Different app states affect how your app interacts with the background download. In iOS, your app could be in the foreground, suspended, or even terminated by the system. See Managing Your App's Life Cycle for more information about these states.
If your app is in the background, the system may suspend your app while the download is performed in another process. In this case, when the download finishes, the system resumes the app and calls the
application(_:. This method receives the session identifier you created in Listing 1 as its second parameter.
This delegate method also receives a completion handler as its final parameter. You should immediately store this handler wherever it makes sense for your app, perhaps as a property of your app delegate, or of your class that implements
URLSession. In Listing 3, this completion handler is stored in an app delegate property called
When all events have been delivered, the system calls the
url method of
URLSession. At this point, fetch the
background stored by the app delegate in Listing 3 and execute it. Listing 4 shows this process.
Note that because
url may be called on a secondary queue, it needs to explicitly execute the handler (which was received from a UIKit method) on the main queue.
Recreate the Session If the App Was Terminated
If the system terminated the app while it was suspended, the system relaunches the app in the background. As part of your launch time setup, recreate the background session (see Listing 1), using the same session identifier as before, to allow the system to reassociate the background download task with your session. You do this so your background session is ready to go whether the app was launched by the user or by the system. Once the app relaunches, the series of events is the same as if the app had been suspended and resumed, as discussed earlier in Handle App Suspension.
Handle Download Completion and Errors
After the app resumes (or is in the foreground), your implementation of
URLSession receives callbacks to update the status of the transfer.
You handle the completion of the download by implementing
url. Check the
download response to see if a server-side error code like
404 is indicated; if so, there is no downloaded file to retrieve and you should abort. If the download is successful, the final parameter is a local URL where the file has been stored. This location is valid only until the end of the callback, so you must move it to another location, such as the app’s Documents directory.
Listing 5 shows an implementation of
url. The implementation completes the background download of a large file by checking for a server-side error and then moving the file to the Documents directory.
To handle a client-side download error, like failing to connect to the host, implement
url. This method is called when any task completes; you only have to handle an error if the final parameter is non-
Comply with Background Transfer Limitations
With background sessions, the actual transfer is performed by a process that is separate from your app’s process. Because restarting your app’s process is fairly expensive, a few features are unavailable, resulting in the following limitations:
The session must provide a delegate for event delivery. (For uploads and downloads, the delegates behave the same as for in-process transfers.)
Only HTTP and HTTPS protocols are supported (no custom protocols).
Redirects are always followed. As a result, even if you have implemented
url, it is not called.
Session(_: task: will Perform HTTPRedirection: new Request: completion Handler:)
Only upload tasks from a file are supported (uploads from data instances or a stream fail after the app exits).