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?
GitHub Authorization
To fetch your private repositories, you need to log in to GitHub through your app. There are two ways an app can get authorization to access GitHub API:
- Basic Authentication: This involves passing the username and password as part of the request.
- OAuth 2.0 token: OAuth 2.0 is an authorization framework that gives an app access to user accounts for an HTTP service.
In this tutorial, you’ll learn to work with an OAuth 2.0 token.
OAuth Overview
There are several steps to authorize an app to access user repositories via OAuth 2.0:
- The app makes a network request for authorization.
- Then, the user logs in to GitHub for the authorization to succeed.
- Next, GitHub redirects back to the app with a temporary code.
- The app requests an access token using that temporary code.
- On receiving the access token, the app makes an API request to fetch the user’s private repositories. The request’s authorization header will contain the access token.
Next, you’ll create a GitHub OAuth app.
Creating GitHub OAuth App
Log in to GitHub and follow these steps to create an OAuth app with the settings shown below:
- Enter GitOnFire as the Application name.
- Enter https://www.raywenderlich.com/ as Homepage URL.
- Skip the Application description.
- Enter gitonfire:// as the Authorization callback URL.
Logging Into GitHub
Once you’ve registered an app, copy the Client ID and Client Secret values. Then in your Xcode project, open GitHubConstants.swift and update clientID
and clientSecret
with the corresponding values.
Next, open GitAPIManager.swift and add the following method just before the closing brace:
func fetchAccessToken(
accessCode: String,
completion: @escaping (Bool) -> Void
) {
// 1
let headers: HTTPHeaders = [
"Accept": "application/json"
]
// 2
let parameters = [
"client_id": GitHubConstants.clientID,
"client_secret": GitHubConstants.clientSecret,
"code": accessCode
]
// 3
sessionManager.request(
"https://github.com/login/oauth/access_token",
method: .post,
parameters: parameters,
headers: headers)
.responseDecodable(of: GitHubAccessToken.self) { response in
guard let cred = response.value else {
return completion(false)
}
TokenManager.shared.saveAccessToken(gitToken: cred)
completion(true)
}
}
Here’s a step-by-step breakdown:
To learn more about using keychain and storing secure information, read this KeyChain Services API Tutorial for Passwords in Swift.
- You define the headers for the request.
Accept
withapplication/json
tells the server the app wants the response in JSON format. - Then you define the query parameters
client_id
,client_secret
andcode
. These parameters are sent as part of the request. - You make a network request to fetch the access token. The response is decoded to
GitHubAccessToken
. TheTokenManager
utility class helps store the token in the keychain.To learn more about using keychain and storing secure information, read this KeyChain Services API Tutorial for Passwords in Swift.
Open LoginViewController.swift. In getGitHubIdentity()
, replace //TODO: Call to fetch access token will be added here
with the following:
GitAPIManager.shared.fetchAccessToken(accessCode: value) { [self] isSuccess in
if !isSuccess {
print("Error fetching access token")
}
navigationController?.popViewController(animated: true)
}
Here, you make a call to fetch the access token using the temporary code. Once the response succeeds, the controller shows the list of repositories.
Now open RepositoriesViewController.swift. In viewDidLoad()
, remove the following line :
loginButton.isHidden = true
This displays the login button. Build and run.
Tap Login to log in. The browser will then redirect you back to the app, and the login button will change to logout. You’ll see the access token and scope in the console.
Great job! Now it’s time to fetch your repositories.
Fetching User Repositories
Open GitAPIManager.swift. In GitAPIManager
, add the following method:
func fetchUserRepositories(completion: @escaping ([Repository]) -> Void) {
//1
let url = "https://api.github.com/user/repos"
//2
let parameters = ["per_page": 100]
//3
sessionManager.request(url, parameters: parameters)
.responseDecodable(of: [Repository].self) { response in
guard let items = response.value else {
return completion([])
}
completion(items)
}
}
Here’s what you added:
- You define the URL to fetch your repositories.
- The
per_page
query parameter determines the maximum number of repositories returned per response. The maximum results you can get per page is 100. - Next, you make a request to fetch your repositories. You then decode the response into an array of
Repository
and pass it in the completion block.
Next, open RepositoriesViewController.swift and find fetchAndDisplayUserRepositories()
. Replace //TODO: Add more here..
with the following:
//1
loadingIndicator.startAnimating()
//2
GitAPIManager.shared.fetchUserRepositories { [self] repositories in
//3
self.repositories = repositories
loadingIndicator.stopAnimating()
tableView.reloadData()
}
Here’s a code breakdown:
By default, Alamofire calls the response handlers on the main queue. So, you don’t have to add code to switch to the main thread to update UI.
- You display a loading indicator before making a network request.
- Then, you make a network request to fetch your repositories.
- Once your repositories are fetched, you set
repositories
with the response and dismiss the loading indicator. You then reload the table view to show the repositories.By default, Alamofire calls the response handlers on the main queue. So, you don’t have to add code to switch to the main thread to update UI.
Build and run.
The list is empty! Check the Xcode console, and you’ll see a 401 unauthorized request.
You have to pass in the access token in a header for authorization. You could add anAuthentication
header inside fetchUserRepositories(completion:)
in GitAPIManager
. However, the process of adding headers individually for each request may become repetitive.
To help avoid this, Alamofire provides RequestInterceptor
, a protocol that enables powerful per-session and per-request capabilities.
Request Overview
Before diving into RequestInterceptor
, you should understand the different types of Request
s.
Alamofire’s Request
is a superclass of all requests. There are several types:
-
DataRequest: Encapsulates
URLSessionDataTask
by downloading the server response into data stored in memory. -
DataStreamRequest: Encapsulates
URLSessionDataTask
and streams data from an HTTP connection over time. -
UploadRequest: Encapsulates
URLSessionUploadTask
and uploads data to a remote server. -
DownloadRequest: Encapsulates
URLSessionDownloadTask
by downloading response data to the disk.
Each request starts in an initialized
state. It can either be suspended
, resumed
or canceled
during its lifetime. The request ends in a finished
state.
Currently, you’re using a DataRequest to fetch your repositories. Now you’re going to intercept your requests using RequestInterceptor
.
RequestInterceptor Overview
Alamofire’s RequestInterceptor
consists of two protocols: RequestAdapter
and RequestRetrier
.
RequestAdapter
lets you inspect and mutate each request before sending it. This is ideal when every request includes an Authorization header.
RequestRetrier
retries a request that encountered an error.