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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Alamofire Tutorial for iOS: Advanced Usage
25 mins
- Getting Started
- Custom Session and URLSessionConfiguration
- Customizing Session
- Logging Network Requests and Responses Using Event Monitor
- GitHub Authorization
- OAuth Overview
- Creating GitHub OAuth App
- Logging Into GitHub
- Fetching User Repositories
- Request Overview
- RequestInterceptor Overview
- Integrating RequestInterceptor
- Routing Requests and URLRequestConvertible
- Network Reachability
- Caching Using ResponseCacher
- Where to Go From Here?
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. :]
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.
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:
- You define the URL to search repositories.
- 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.
- 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 ofRepository
, 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:
- Define
sessionManager
as a customSession
. - Then create an instance of
URLSessionConfiguration
fromURLSessionConfiguration.af.default
. The default AlamofireURLSessionConfiguration
adds Accept-Encoding, Accept-Language and User-Agent headers. - Set
timeoutIntervalForRequest
on the configuration to 30 seconds, which applies to all the requests in that session. - 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.
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.
-
EventMonitor
requires aDispatchQueue
which dispatches all events. By default,EventMonitor
uses the main queue.You initialize
queue
with a customDispatchQueue
to maintain performance. It’s a serial queue that handles all the events for the session. -
requestDidFinish(_:)
is called when the request finishes. Then, you print thedescription
of the request to see the HTTP method and the request URL in the console. -
request(_:didParseResponse:)
is called when the response is received. UsingJSONSerialization
, 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.
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. :]