Alamofire Tutorial for iOS: Advanced Usage

In this tutorial, you’ll learn about the advanced usage of Alamofire. Topics include handling OAuth, network logging, reachability, caching and more. By Vidhur Voora.

5 (23) · 3 Reviews

Download materials
Save for later
Share

Alamofire is one of the most popular and widely used Swift networking libraries. Built on Apple’s Foundation networking stack, it provides an elegant API to make network requests. With over thirty-thousand stars on GitHub, it’s one of the top-rated Swift repositories.

Today you’ll dive in and master it. :]

In this tutorial, you’ll get an introduction to the advanced use of Alamofire. You’ll apply these concepts while building a GitHub client app, GitOnFire. Along the way, you’ll learn how to:

  • Handle authentication using OAuth.
  • Log network requests and responses.
  • Retry network requests.
  • Check for network reachability.
  • Cache the network responses.

Here’s a fun fact: Alamofire got its name from Alamo Fire flower, one of the official state flowers of Texas. :]

Note: This tutorial assumes you’re familiar with Apple’s URL Loading System. If you’re new to Alamofire, check out Alamofire 5 For iOS: Getting Started. You’ll also need a GitHub account.

Getting Started

Download the starter project by clicking the Download Materials button at the top or bottom of this page.

You’ll work on an app called GitOnFire. The starter project comes with the Alamofire network library and a basic integration of GitHub API.

Open the project in the starter folder. Build and run.

GitOnFire App Overview

You’ll see a list of the most popular Swift repositories in GitHub. Notice Alamofire’s position on that list. :]

Specify a search-text to get the related list of popular repositories. Tap a repository’s name to see its recent commits.

You’ll update the network calls to use a custom URLSessionConfiguration. You’ll also integrate OAuth login and fetch repositories from your account.

These are the files you’ll work on first:

  • GitAPIManager.swift: Fetches the repositories and commits from GitHub using Alamofire.
  • RepositoriesViewController.swift: Displays the list of repositories.
  • LoginViewController.swift: Handles GitHub OAuth login.

In this tutorial, you’ll use GitHub APIs which deal with OAuth authentication, fetching repositories and commits. For an extensive list of all the GitHub APIs and their uses, please refer to this API documentation.

Custom Session and URLSessionConfiguration

Open GitAPIManager.swift and find searchRepositories(query:completion:). The implementation for searching GitHub repositories is already in place. You’ll use this opportunity to understand the inner workings within the method.

func searchRepositories(
  query: String,
  completion: @escaping ([Repository]) -> Void
) {
  // 1
  let url = "https://api.github.com/search/repositories"
  // 2
  var queryParameters: [String: Any] = [
    "sort": "stars",
    "order": "desc",
    "page": 1
  ]
  queryParameters["q"] = query
  // 3
  AF.request(url, parameters: queryParameters).responseDecodable(
    of: Repositories.self) { response in
      guard let items = response.value else {
        return completion([])
      }
      completion(items.items)
    }
}

Here’s a step-by-step breakdown:

  1. You define the URL to search repositories.
  2. Then, you create an array of query parameters to fetch the repositories. You specify a descending sort order based on the number of stars for the repository.
  3. Next, you make the network request using Alamofire’s default session AF. The method decodes the received response and returns it in a completion block as an array of Repository, your custom model.

The default timeout for each request is 60 seconds. To update the timeout interval to 30 seconds, you can specify a requestModifier as part of the request, as shown below as reference:

AF.request(url, parameters: queryParameters) { urlRequest in
  urlRequest.timeoutInterval = 30
}

You can specify requestModifier as a trailing block when constructing the request. But, what do you do if all the requests for a session need timeout intervals? You use a custom URLSessionConfiguration.

Customizing Session

Alamofire provides Session, which is similar to URLSession in terms of responsibility. It helps create and manage different requests and provides common functionality for all requests, such as interception, response caching and more. You’ll learn more about different types of requests later in this tutorial.

You can customize session behavior by using a URLSessionConfiguration with the desired configuration. Add the following code to GitAPIManager:

//1
let sessionManager: Session = {
  //2
  let configuration = URLSessionConfiguration.af.default
  //3
  configuration.timeoutIntervalForRequest = 30
  //4
  return Session(configuration: configuration)
}()

Here you:

  1. Define sessionManager as a custom Session.
  2. Then create an instance of URLSessionConfiguration from URLSessionConfiguration.af.default. The default Alamofire URLSessionConfiguration adds Accept-Encoding, Accept-Language and User-Agent headers.
  3. Set timeoutIntervalForRequest on the configuration to 30 seconds, which applies to all the requests in that session.
  4. Once you’ve defined the configuration, you create an instance of a Session by passing in the custom configuration.

Now you’ll use this sessionManager for all your network requests. In searchRepositories(query:completion:), replace:

AF.request(url, parameters: queryParameters)

With:

sessionManager.request(url, parameters: queryParameters)

Here, you make the request with sessionManager instead of AF.

Next in fetchCommits(for:completion:), replace:

AF.request(url)

With:

sessionManager.request(url)

Now both network requests have the request timeout interval set to 30 seconds.

Next, you’ll see the advantage of using custom sessions.

In sessionManager, add the following code below configuration.timeoutIntervalForRequest = 30:

configuration.waitsForConnectivity = true

Here, you set waitsForConnectivity to true which makes the session wait for network connectivity before making the request. You must set all custom configurations for URLSessionConfiguration before adding them to Session. If you mutate the configuration properties after adding to Session they won’t have any effect.

To see the code in action. Turn the WiFi off. Build and run.

Alamofire Wait for connectivity

The app loads, showing an empty list with a loading indicator. Then, turn the WiFi on. Within a few seconds, the repositories will load. Doesn’t it feel like magic?

Later on in this tutorial, you’ll learn how to monitor and handle network reachability.

Next, you’ll learn how to log network requests and responses using Event Monitor.

Logging Network Requests and Responses Using Event Monitor

So far, you’ve made network requests to fetch repositories and commits and displayed the results in a table view. That’s cool, but you can go further and see the raw network requests and responses.

Alamofire provides a powerful way to gain insight into all the internal events via the EventMonitor protocol. EventMonitor includes several Alamofire events such as URLSessionDelegate request events. This makes EventMonitor ideal for logging events.

Create a new Swift file named GitNetworkLogger.swift in Networking group. Add the following code:

import Alamofire

class GitNetworkLogger: EventMonitor {
  //1
  let queue = DispatchQueue(label: "com.raywenderlich.gitonfire.networklogger")
  //2
  func requestDidFinish(_ request: Request) {
    print(request.description)
  }
  //3
  func request<Value>(
    _ request: DataRequest,
    didParseResponse response: DataResponse<Value, AFError>
  ) {
    guard let data = response.data else {
      return
    }
    if let json = try? JSONSerialization
      .jsonObject(with: data, options: .mutableContainers) {
        print(json)
    }
  }
}

Here’s a code breakdown:

You initialize queue with a custom DispatchQueue to maintain performance. It’s a serial queue that handles all the events for the session.

  1. EventMonitor requires a DispatchQueue which dispatches all events. By default, EventMonitor uses the main queue.

    You initialize queue with a custom DispatchQueue to maintain performance. It’s a serial queue that handles all the events for the session.

  2. requestDidFinish(_:) is called when the request finishes. Then, you print the description of the request to see the HTTP method and the request URL in the console.
  3. request(_:didParseResponse:) is called when the response is received. Using JSONSerialization, you render the response as JSON and then print it to the console.

Open GitAPIManager.swift. Add the following code below configuration.waitsForConnectivity = true in sessionManager:

let networkLogger = GitNetworkLogger()

Here, you define networkLogger as an instance of GitNetworkLogger.

Now replace return Session(configuration: configuration) with the following:

return Session(configuration: configuration, eventMonitors: [networkLogger])

The networkLogger is passed in an array to eventMonitors during Session initialization. Build and run.

Network Logging

Now you’ll see all the network requests and responses logged in the console. Great job!

So far, you’ve fetched public repositories. Now it’s time to fetch repositories from your own GitHub account. Get ready for some authorization fun. :]