Networking in Swift: How to download a file with URLSession [Swift 3]

Update November 2016: Fully updated for Xcode 8 and Swift 3.

You will often need to download content to use in your app. NSURLConnection used to be a great interface to perform networking tasks along with NSURLSession. But since it’s deprecated in iOS 9, Apple recommends you use the URLSession class from now on for all server operations, like http requests, ftp operations and file download/upload tasks.

In this tutorial, you gonna use the URLSession download task to download a file remotely to your app and report the progress to the user while bytes are being downloaded.

Let’s begin by downloading the starter project here.

The project you will build by the end of this tutorial will download a PDF file and load it on the screen.

If you take a look at the user interface in the starter project, there is already four buttons to manage the download operation. The common states for a download task are the pause/resume/stop and start actions. There is also a progress view to report the download progress instantly to the user.

The URLSession hierarchy requires a specific configuration. When a session object is about to be created, it needs a configuration object that define the behavior and policies to use when uploading and downloading content. In this tutorial, you gonna use a background session configuration in order to allow HTTP download to be performed in the background.

Select the ViewController.swift file from the Project navigator view and add the following properties declarations:

The properties above are declared as implicitly unwrapped optionals which explains why you put the exclamation mark after their types. Declaring the properties this way will relieve us from using the question mark (?) each time you use the property to unwrap its value, since we know the property value is confirmed to exist immediately after the optional is first defined.

Next, locate the viewDidLoad method and implement the following code inside:

The code above will instantiate a background session configuration object and use it to create an URLSession instance. As I said earlier, the background session configuration is what enables the session object to carry on the download in the background.

You also set the progress property of the UIProgressView object to 0 to get ready for the download operation.

Good, now locate the startDownload action method and copy the following code inside:

This will construct an URL object for a “PDF ebook”. Then it will instantiate an URLSessionDownloadTask object to initiate and manage the download operation of the file. Calling the resume method will start the download task immediately.

Starting the download operation will imply some events to be raised by the download task object (i.e: Bytes are being downloaded, file did finish downloading, etc). To react to such events accordingly, you will need to implement some protocol methods.

First, make the class conform to the URLSessionDownloadDelegate protocol by changing the class declaration to the following:

Next, implement the following URLSessionDownloadDelegate protocol methods before the class closing bracket:

Let’s breakdown the code above:

// 1: This protocol method will tell the delegate that the download task has finished downloading. You just checked whether the file already exists. If so, the code will load the file immediately, otherwise, it will move it to a new location before loading it.

Embedding the moveItem method inside a do-catch bloc is mandatory since this method may throw errors.

// 2: Here you just benefit from the useful informations this protocol method gives you. Precisely the totalBytesWritten and totalBytesExpectedToWrite parameters. As the method periodically informs the delegate about the download progress, you just calculated the downloaded bytes and updated the progress view accordingly.

Let’s implement the showFileWithPath method which will load the PDF file once it’s downloaded. Copy the following code inside the class:

The method above will use the path string to load the file using the UIDocumentInteractionController class.

UIDocumentInteractionController requires a delegate as well as implementing a UIDocumentInteractionControllerDelegate protocol method in order to be able to load a preview screen for the file.

Copy the following protocol method before the class closing bracket:

The method above will return the current view controller as the preview controller of the PDF file.

Next, change the class declaration to the following:

Each URLSession task may encounter an issue and end up with an error, it’s recommended that we react to such scenario accordingly. To do so, copy the following URLSessionTaskDelegate protocol method inside the class:

Let’s finish up by implementing the remaining action methods for the pause/resume/cancel operations.

Change the pause, the resume and the cancel methods implementations to the following:

Before you run the project, let’s disable the App Transport Security so that it won’t block access to the URL. Select the Info.plist file from the Project navigator view and make the following changes:

Disable the app transport security (ATS)

That’s it, run the project and enjoy your work once again 🙂

As usual, you can download the final project here.

Feel free to leave a comment below, I’d love to hear from you.

Also, the tutorial forum thread is here in case you have related questions. Feel free to open a new thread if you want to ask me other technical questions, I am here to help you.

About Malek

Malek is a passionate iOS Engineer and Founder of Medigarage Studios, a small mobile games startup. I started my iOS adventures in 2011 and since then I fell in love with it. You can hire me for your project, get in touch by Email to discuss further details. Also, feel free to reach out on Twitter and Google+.

  • Pingback: Android & iOS Application Development | Just another My blog Sites site()

  • only one PDF file download i need to more download by selected table view cells

  • Andy

    The app compiles and runs on an iPhone 6 Plus and downloads the PDF but unfortunately the progress bar shows nothing. What can I do to correct this?

  • Malek_T

    Hi Andy, I tested again with Xcode 7 and Xcode 8 and the progress bar is running correctly. Are you using a different code than in the tutorial?

  • Andy

    Hi Malek

    Thanks for reply and I thought I hadn’t change anything but download tutorial again and you are correct it runs perfectly, sorry I raised comment. I now have learn to use this tutorial code to add the feature to my JSON download.

  • Malek_T

    Hi Andy, no worries. You welcome 🙂

  • bagus widyanto

    hi andy, i want to learn download sound from url, but many file and the name based from database. what this tutorial can be used? thanks

  • Basil

    I have problem , I have 2 tableview , both using same ViewController , because I got the data from server and change the table depend of cell i clicked on first tableview , If i Download files it downloaded without problem , but when I click Back button and select another Cell then try to download I got this error
    “A background URLSession with identifier backgroundSession already exists!”
    and the Progress view won’t update but the file is downloaded !!

    this problem happen every time I go back and return to same view controller

    I hope you are understand my problem

  • Basil