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
Update note: Felipe Laso-Marsetti updated this tutorial for Swift 5.0, Xcode 10.2 and iOS 12. Ken Toh wrote the original and Audrey Tam completed an earlier update.

Whether an app retrieves application data from a server, updates your social media status or downloads remote files to disk, network requests are what make the magic happen. To help you with the many requirements for network requests, Apple provides URLSession, a complete networking API for uploading and downloading content.

In this tutorial, you’ll learn how to build Half Tunes, an app that queries the iTunes Search API, then downloads 30-second previews of songs. The finished app will support background transfers and let the user pause, resume or cancel in-progress downloads.

Getting Started

Use the Download Materials button at the top or bottom of this tutorial to download the starter project.

The starter project contains a user interface to search for songs and display search results, networking classes with some stubbed functionality and helper methods to store and play tracks. This lets you focus on implementing the networking aspects of the app.

Build and run the project. You’ll see a view with a search bar at the top and an empty table view below:

Half Tune App's Starter Screen

Type a query in the search bar and tap Search. The view remains empty. Don’t worry though, you’ll change this with your new URLSession calls.

URLSession Overview

Before you begin, it’s important to understand URLSession and its constituent classes, so take a look at the quick overview below.

URLSession is both a class and a suite of classes for handling HTTP- and HTTPS-based requests:

URLSession Diagram

URLSession is the key object responsible for sending and receiving requests. You create it via URLSessionConfiguration, which comes in three flavors:

  • default: Creates a default configuration object that uses the disk-persisted global cache, credential and cookie storage objects.
  • ephemeral: Similar to the default configuration, except that you store all of the session-related data in memory. Think of this as a “private” session.
  • background: Lets the session perform upload or download tasks in the background. Transfers continue even when the app itself is suspended or terminated by the system.

URLSessionConfiguration also lets you configure session properties such as timeout values, caching policies and HTTP headers. Refer to Apple’s documentation for a full list of configuration options.

URLSessionTask is an abstract class that denotes a task object. A session creates one or more tasks to do the actual work of fetching data and downloading or uploading files.

Understanding Session Task Types

There are three types of concrete session tasks:

  • URLSessionDataTask: Use this task for GET requests to retrieve data from servers to memory.
  • URLSessionUploadTask: Use this task to upload a file from disk to a web service via a POST or PUT method.
  • URLSessionDownloadTask: Use this task to download a file from a remote service to a temporary file location.

URLSession Task Types

You can also suspend, resume and cancel tasks. URLSessionDownloadTask has the extra ability to pause for future resumption.

Generally, URLSession returns data in two ways:

  • Via a completion handler when a task finishes, either successfully or with an error; or,
  • By calling methods on a delegate that you set when you create the session.

Now that you have an overview of what URLSession can do, you’re ready to put the theory into practice!

Putting Theory Into Practice

DataTask and DownloadTask

You’ll start by creating a data task to query the iTunes Search API for the user’s search term.

In SearchViewController.swift, searchBarSearchButtonClicked enables the network activity indicator on the status bar to show the user that a network process is running. Then it calls getSearchResults(searchTerm:completion:), which is stubbed out in QueryService.swift. You’re about to build it out to make the network request.

In QueryService.swift, replace // TODO 1 with the following:

let defaultSession = URLSession(configuration: .default)

And // TODO 2 with:

var dataTask: URLSessionDataTask?

Here’s what you’ve done:

  1. Created a URLSession and initialized it with a default session configuration.
  2. Declared URLSessionDataTask, which you’ll use to make a GET request to the iTunes Search web service when the user performs a search. The data task will be re-initialized each time the user enters a new search string.

Next, replace the content in getSearchResults(searchTerm:completion:) with the following:

// 1
dataTask?.cancel()
    
// 2
if var urlComponents = URLComponents(string: "https://itunes.apple.com/search") {
  urlComponents.query = "media=music&entity=song&term=\(searchTerm)"      
  // 3
  guard let url = urlComponents.url else {
    return
  }
  // 4
  dataTask = 
    defaultSession.dataTask(with: url) { [weak self] data, response, error in 
    defer {
      self?.dataTask = nil
    }
    // 5
    if let error = error {
      self?.errorMessage += "DataTask error: " + 
                              error.localizedDescription + "\n"
    } else if 
      let data = data,
      let response = response as? HTTPURLResponse,
      response.statusCode == 200 {       
      self?.updateSearchResults(data)
      // 6
      DispatchQueue.main.async {
        completion(self?.tracks, self?.errorMessage ?? "")
      }
    }
  }
  // 7
  dataTask?.resume()
}

Taking each numbered comment in turn:

  1. For a new user query, you cancel any data task that already exists, because you want to reuse the data task object for this new query.
  2. To include the user’s search string in the query URL, you create URLComponents from the iTunes Search base URL, then set its query string. This ensures that your search string uses escaped characters. If you get back an error message, omit the media and entity components: See this forum post.
  3. The url property of urlComponents is optional, so you unwrap it to url and return early if it’s nil.
  4. From the session you created, you initialize a URLSessionDataTask with the query url and a completion handler to call when the data task completes.
  5. If the request is successful, you call the helper method updateSearchResults, which parses the response data into the tracks array.
  6. You switch to the main queue to pass tracks to the completion handler.
  7. All tasks start in a suspended state by default. Calling resume() starts the data task.

In SearchViewController, take a look at the completion closure in the call to getSearchResults(searchTerm:completion:). After hiding the activity indicator, it stores results in searchResults then updates the table view.

Note: The default request method is GET. If you want a data task to POST, PUT or DELETE, create a URLRequest with url, set the request’s HTTPMethod property then create a data task with the URLRequest instead of with the URL.

Build and run your app. Search for any song and you’ll see the table view populate with the relevant track results like so:

Half Tunes Screen With Relevant Track Results

With some URLSession code, Half Tunes is now a bit functional!

Being able to view song results is nice, but wouldn’t it be better if you could tap a song to download it? That’s your next order of business. You’ll use a download task, which makes it easy to save the song snippet in a local file.