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.

4.7 (58) · 2 Reviews

Download materials
Save for later
Share
You are currently viewing page 4 of 4 of this article. Click here to view the first page.

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:

Half Tunes App with Download Progress Features

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.

Note: If the user terminates the app by force-quitting from the app switcher, the system will cancel all the session’s background transfers and won’t attempt to relaunch the app.

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.

Note: You must not create more than one session for a background configuration, because the system uses the configuration’s identifier to associate tasks with the session.

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:

Completed Half Tunes App With All Functions Enabled

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!