Sending the Request

A URL request encapsulates information about the communication from the application to the server. Most importantly, it specifies the URL of the server for the request, but it also has a timeout interval, a cache policy, and other metadata about the request. A request is represented by the URLRequest class. Check out the For the More Curious section at the end of this chapter for more information.

The URLSession API is a collection of classes that use a request to communicate with a server in a number of ways. The URLSessionTask class is responsible for communicating with a server. The URLSession class is responsible for creating tasks that match a given configuration.

In Photorama, a new class, PhotoStore, will be responsible for initiating the web service requests. It will use the URLSession API and the FlickrAPI struct to fetch a list of interesting photos and download the image data for each photo.

Create a new Swift file named PhotoStore and declare the PhotoStore class.

Listing 20.10  Creating the PhotoStore class (PhotoStore.swift)

import Foundation

class PhotoStore {

}

URLSession

Let’s look at a few of the properties on URLRequest:

allHTTPHeaderFields

A dictionary of metadata about the HTTP transaction, including character encoding and how the server should handle caching.

allowsCellularAccess

A Boolean that represents whether a request is allowed to use cellular data.

cachePolicy

The property that determines whether and how the local cache should be used.

httpMethod

The request method. The default is GET, and other common values are POST, PUT, and DELETE.

timeoutInterval

The maximum duration a connection to the server will be attempted for.

The class that communicates with the web service is an instance of URLSessionTask. There are three kinds of tasks: data tasks, download tasks, and upload tasks. URLSessionDataTask retrieves data from the server and returns it as Data in memory. URLSessionDownloadTask retrieves data from the server and returns it as a file saved to the filesystem. URLSessionUploadTask sends data to the server.

Often, you will have a group of requests that have many properties in common. For example, maybe some downloads should never happen over cellular data, or maybe certain requests should be cached differently than others. It can become tedious to configure related requests the same way.

This is where URLSession comes in handy. URLSession acts as a factory for URLSessionTask instances. The session is created with a configuration that specifies properties that are common across all the tasks that it creates. Although many applications might only need to use a single instance of URLSession, having the power and flexibility of multiple sessions is a great tool to have at your disposal.

In PhotoStore.swift, add a property to hold on to an instance of URLSession.

Listing 20.11  Adding a URLSession property (PhotoStore.swift)

class PhotoStore {

    private let session: URLSession = {
        let config = URLSessionConfiguration.default
        return URLSession(configuration: config)
    }()

}

In PhotoStore.swift, implement the fetchInterestingPhotos() method to create a URLRequest that connects to api.flickr.com and asks for the list of interesting photos. Then, use the URLSession to create a URLSessionDataTask that transfers this request to the server.

Listing 20.12  Implementing a method to start the web service request (PhotoStore.swift)

func fetchInterestingPhotos() {

    let url = FlickrAPI.interestingPhotosURL
    let request = URLRequest(url: url)
    let task = session.dataTask(with: request) {
        (data, response, error) in

        if let jsonData = data {
            if let jsonString = String(data: jsonData,
                                       encoding: .utf8) {
                print(jsonString)
            }
        } else if let requestError = error {
            print("Error fetching interesting photos: (requestError)")
        } else {
            print("Unexpected error with the request")
        }
    }
    task.resume()
}

Creating the URLRequest is fairly straightforward: You create a URL instance using the FlickrAPI struct and instantiate a request object with it.

By giving the session a request and a completion closure to call when the request finishes, you ensure that the session will return an instance of URLSessionTask. Because Photorama is requesting data from a web service, the type of task will be an instance of URLSessionDataTask. Tasks are always created in the suspended state, so calling resume() on the task will start the web service request. For now, the completion block will just print out the JSON data returned from the request.

To make a request, PhotosViewController will call the appropriate methods on PhotoStore. To do this, PhotosViewController needs a reference to an instance of PhotoStore.

At the top of PhotosViewController.swift, add a property to hang on to an instance of PhotoStore.

Listing 20.13  Adding a PhotoStore property (PhotosViewController.swift)

class PhotosViewController: UIViewController {

    @IBOutlet private var imageView: UIImageView!
    var store: PhotoStore!

The store is a dependency of the PhotosViewController. You will use property injection to give the PhotosViewController its store dependency, just as you did with the view controllers in LootLogger.

Open SceneDelegate.swift and use property injection to give the PhotosViewController an instance of PhotoStore.

Listing 20.14  Injecting the PhotoStore instance (SceneDelegate.swift)

func scene(_ scene: UIScene,
           willConnectTo session: UISceneSession,
           options connectionOptions: UIScene.ConnectionOptions) {
    guard let _ = (scene as? UIWindowScene) else { return }

    let rootViewController = window!.rootViewController as! UINavigationController
    let photosViewController =
        rootViewController.topViewController as! PhotosViewController
    photosViewController.store = PhotoStore()
}

Now that the PhotosViewController can interact with the PhotoStore, kick off the web service exchange when the view controller is coming onscreen for the first time.

In PhotosViewController.swift, override viewDidLoad() and fetch the interesting photos.

Listing 20.15  Initiating the web service request (PhotosViewController.swift)

override func viewDidLoad() {
    super.viewDidLoad()

    store.fetchInterestingPhotos()
}

Build and run the application. A string representation of the JSON data coming back from the web service will print to the console. (If you do not see anything print to the console, make sure you typed the URL and API key correctly.)

The response will look something like Figure 20.4.

Figure 20.4  Web service console output

Web service console output
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.58.252.8