AFNetworking has always been one of my favorite libraries and Alamofire is just as easy to like. Since the introduction of URLSession
in iOS 7 and macOS Mavericks, I have been more reluctant to include either libraries into my projects.
The reason is simple. URLSession
offers an easy-to-use, modern API for networking. It offers flexibility and several features many developers have been asking for. If a project can do without another dependency, then that is something worth considering.
URLSession
is the successor of NSURLConnection
. For many years, NSURLConnection
has been the workhorse for networking on iOS and macOS. Most developers used or created a wrapper around NSURLConnection
to hide the less enjoyable aspects of the NSURLConnection
interface.
In addition to being a class, URLSession
is a technology that provides the infrastructure for networking, exposed through a modern and elegant API. In this series, I introduce you to the URLSession
stack. You learn how easy it is to get started with URLSession
and you discover that URLSession
exposes a flexible API that should meet anyone's networking needs.
Meet the Family
The URLSession
family includes a number of key classes. The URLSession
class is the central component of the URLSession
stack. It is used to create and configure network requests.
Another important class is URLSessionConfiguration
. A session configuration object is used to configure a URLSession
instance. The session is in charge of managing requests. The session configuration defines the behavior of the session. This is especially interesting for uploading and downloading data.
The workhorses of URLSession
are URLSessionTask
and its concrete subclasses. The subclasses you will interact with most are:
URLSessionDataTask
for fetching dataURLSessionUploadTask
for uploading dataURLSessionDownloadTask
for downloading data
URLSessionDataTask
and URLSessionDownloadTask
directly inherit from URLSessionTask
. URLSessionUploadTask
is a subclass of URLSessionDataTask
.
A URLSessionTask
object is always associated with a session. You can create a URLSessionTask
object by asking the session for one. This is illustrated by the following example. We discuss the details a bit later in this tutorial.
// Reference to Shared Session
let session = URLSession.shared
// Create Request
let request = URLRequest(url: url)
// Create Data Task
let dataTask = session.dataTask(with: request)
Fetching Data
Now that we have met the family, it is time to create a request to see how the various pieces fit together. Create a new project in Xcode based on the Single View Application template. Set Product Name to Networking and Language to Swift.
To illustrate how the URLSession
stack works, we will fetch an image from the web and display it in an image view. This simple example will show you how easy it is to create a request, schedule it, and handle its response.
Open Main.storyboard and add an image view to the View Controller Scene. Add the required constraints to pin the image view to the edges of its superview. Open the Attributes Inspector and set Mode to Aspect Fit.
Open ViewController.swift and create an outlet for the image view. Revisit Main.storyboard and connect the outlet to the image view.
import UIKit
class ViewController: UIViewController {
// MARK: - Properties
@IBOutlet var imageView: UIImageView!
...
}
Open ViewController.swift and update viewDidLoad()
as shown below.
override func viewDidLoad() {
super.viewDidLoad()
// Obtain Reference to Shared Session
let sharedSession = URLSession.shared
if let url = URL(string: "https://goo.gl/wV9G4I") {
// Create Request
let request = URLRequest(url: url)
// Create Data Task
let dataTask = sharedSession.dataTask(with: request, completionHandler: { (data, response, error) -> Void in
if let data = data, let image = UIImage(data: data) {
DispatchQueue.main.async {
self.imageView.image = image
}
}
})
dataTask.resume()
}
}
We obtain a reference to a URLSession
instance by invoking shared
on the URLSession
class. This returns a shared session object, a singleton, that uses the global cache, cookie storage, and credential storage. There are other options to create a session, but the shared session is fine for this example.
We then create a URL
instance and use that to create a request, an instance of the URLRequest
class. To make a request, we ask the session for a data task by invoking dataTask(with:completionHandler:)
. This method accepts two arguments, the request and a closure. The closure accepts three arguments:
- an optional
Data
instance - an optional
URLResponse
instance - and an optional
Error
instance
The closure is executed when the request completes, successfully or unsuccessfully. We use optional binding to safely unwrap the data that is returned to us and we use it to instantiate a UIImage
object. We update the image view with the resulting image.
It is important to point out that we explicitly update the image view on the main thread. The closure we pass to dataTask(with:completionHandler:)
is invoked on a background thread and, therefore, we are required to dispatch updating the image view to the main queue.
Last but not least, we schedule the data task by invoking resume()
on the data task. This is easily overlooked. Run the application in the simulator or on a physical device to see the result.
What's Next?
Using URLSession
is much easier than NSURLConnection
. It is clear Apple decided it was time to rethink networking on iOS and macOS when they created URLSession
. In this tutorial, you learned about the very basics of URLSession
. In the next tutorial, we take a look at the more advanced options of the URLSession
API.
You can download the source files of the tutorial from GitHub.