URLSession Tutorial: Getting Started
In this URLSession tutorial, you’ll learn how to create HTTP requests as well as implement background downloads that can be both paused and resumed. By Felipe Laso-Marsetti.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
URLSession Tutorial: Getting Started
30 mins
- Getting Started
- URLSession Overview
- Understanding Session Task Types
- DataTask and DownloadTask
- Downloading Classes
- URLSession Delegates
- Downloading a Track
- Saving and Playing the Track
- Pausing, Resuming, and Canceling Downloads
- Canceling Downloads
- Pausing Downloads
- Resuming Downloads
- Showing and Hiding the Pause/Resume and Cancel Buttons
- Showing Download Progress
- Displaying the Download’s Progress
- Enabling Background Transfers
- Relaunching Your App
- Testing Your App’s Functionality
- Where to Go From Here?
Displaying the Download’s Progress
Now, update the cell’s configuration to display the progress view and status when a download is in progress.
Open TrackCell.swift. In configure(track:downloaded:download:)
, add the following line inside the if-closure, after the pause button title is set:
progressLabel.text = download.isDownloading ? "Downloading..." : "Paused"
This gives the cell something to show before the first update from the delegate method and while the download is paused.
Now, add the following code below the if-closure, below the isHidden
lines for the two buttons:
progressView.isHidden = !showDownloadControls
progressLabel.isHidden = !showDownloadControls
This shows the progress view and label only while the download is in progress.
Build and run your project. Download any track and you should see the progress bar status update as the download progresses:
Hurray, you’ve made, erm, progress! :]
Enabling Background Transfers
Your app is quite functional at this point, but there’s one major enhancement left to add: Background transfers.
In this mode, downloads continue even when your app is in the background or if it crashes for any reason. This isn’t really necessary for song snippets, which are pretty small, but your users will appreciate this feature if your app transfers large files.
But how can this work if your app isn’t running?
The OS runs a separate daemon outside the app to manage background transfer tasks, and it sends the appropriate delegate messages to the app as the download tasks run. In the event that the app terminates during an active transfer, the tasks will continue to run, unaffected, in the background.
When a task completes, the daemon will relaunch the app in the background. The relaunched app will recreate the background session to receive the relevant completion delegate messages and perform any required actions, such as persisting downloaded files to disk.
You’ll access this magic by creating a session with the background session configuration.
In SearchViewController.swift, in the initialization of downloadsSession
, find the following line of code:
let configuration = URLSessionConfiguration.default
…and replace it with the following line:
let configuration =
URLSessionConfiguration.background(withIdentifier:
"com.raywenderlich.HalfTunes.bgSession")
Instead of using a default session configuration, you’ll use a special background session configuration. Note that you also set a unique identifier for the session to allow your app to create a new background session, if needed.
Relaunching Your App
If a background task completes when the app isn’t running, the app will relaunch in the background. You’ll need to handle this event from your app delegate.
Switch to AppDelegate.swift, replace // TODO 17
with the following code:
var backgroundSessionCompletionHandler: (() -> Void)?
Next, replace // TODO 18
with the following method:
func application(
_ application: UIApplication,
handleEventsForBackgroundURLSession
handleEventsForBackgroundURLSessionidentifier: String,
completionHandler: @escaping () -> Void) {
backgroundSessionCompletionHandler = completionHandler
}
Here, you save the provided completionHandler
as a variable in your app delegate for later use.
application(_:handleEventsForBackgroundURLSession:)
wakes up the app to deal with the completed background task. You’ll need to handle two items in this method:
- First, the app needs to recreate the appropriate background configuration and session using the identifier provided by this delegate method. But since this app creates the background session when it instantiates
SearchViewController
, you’re already reconnected at this point! - Second, you’ll need to capture the completion handler provided by this delegate method. Invoking the completion handler tells the OS that your app’s done working with all background activities for the current session. It also causes the OS to snapshot your updated UI for display in the app switcher.
The place to invoke the provided completion handler is urlSessionDidFinishEvents(forBackgroundURLSession:)
, which is a URLSessionDelegate
method that fires when all tasks on the background session have finished.
In SearchViewController.swift replace // TODO 19
with the following extension:
extension SearchViewController: URLSessionDelegate {
func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
DispatchQueue.main.async {
if let appDelegate = UIApplication.shared.delegate as? AppDelegate,
let completionHandler = appDelegate.backgroundSessionCompletionHandler {
appDelegate.backgroundSessionCompletionHandler = nil
completionHandler()
}
}
}
}
The code above grabs the stored completion handler from the app delegate and invokes it on the main thread. You find the app delegate by getting the shared instance of UIApplication
, which is accessible thanks to the UIKit import.
Testing Your App’s Functionality
Build and run your app. Start a few concurrent downloads and tap the Home button to send the app to the background. Wait until you think the downloads have completed, then double-tap the Home button to reveal the app switcher.
The downloads should have finished, and you should see their new status in the app snapshot. Open the app to confirm this:
You now have a functional music-streaming app! Your move now, Apple Music! :]
Where to Go From Here?
Congratulations! You’re now well-equipped to handle most common networking requirements in your app.
If you want to explore the subject further, there are more URLSession
topics than would fit in this tutorial. For example, you can also try out uploading tasks and session configuration settings such as timeout values and caching policies.
To learn more about these features (and others!), check out the following resources:
- Apple’s URLSession Programming Guide contains comprehensive information on everything you’d want to do.
- Our own Networking with URLSession video course starts with HTTP basics, then goes on to cover tasks, background sessions, authentication, App Transport Security, architecture and unit testing.
- AlamoFire is a popular third-party iOS networking library; we cover the basics of it in our Beginning Alamofire tutorial.
I hope you enjoyed reading this tutorial. If you have any questions or comments, please join the discussion below!