Alamofire 5 Tutorial for iOS: Getting Started
In this Alamofire tutorial, you’ll build an iOS companion app to perform networking tasks, send request parameters, decode/encode responses and more. By Corey Davis.
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 5 Tutorial for iOS: Getting Started
30 mins
- Getting Started
- Using the SW API
- Understanding HTTP, REST and JSON
- Why Use Alamofire?
- Requesting Data
- Using a Codable Data Model
- Method Chaining
- Setting up Your Table View
- Updating the Detail View Controller
- Fetching Multiple Asynchronous Endpoints
- Creating a Data Model for Starships
- Fetching the Starship Data
- Updating Your Table View
- Sending Parameters With a Request
- Decoding Starships
- Searching for Ships
- Display a Ship’s List of Films
- Where to Go From Here?
Creating a Data Model for Starships
Before fetching any starships, you first need a new data model to handle the starship data. Your next step is to create one.
In the Networking group, add a new Swift file. Name it Starship.swift and add the following code:
struct Starship: Decodable {
var name: String
var model: String
var manufacturer: String
var cost: String
var length: String
var maximumSpeed: String
var crewTotal: String
var passengerTotal: String
var cargoCapacity: String
var consumables: String
var hyperdriveRating: String
var starshipClass: String
var films: [String]
enum CodingKeys: String, CodingKey {
case name
case model
case manufacturer
case cost = "cost_in_credits"
case length
case maximumSpeed = "max_atmosphering_speed"
case crewTotal = "crew"
case passengerTotal = "passengers"
case cargoCapacity = "cargo_capacity"
case consumables
case hyperdriveRating = "hyperdrive_rating"
case starshipClass = "starship_class"
case films
}
}
As with the other data models, you simply list all the response data you want to use, along with any relevant coding keys.
You also want to be able to display information about individual ships, so Starship
must conform to Displayable
. Add the following at the end of the file:
extension Starship: Displayable {
var titleLabelText: String {
name
}
var subtitleLabelText: String {
model
}
var item1: (label: String, value: String) {
("MANUFACTURER", manufacturer)
}
var item2: (label: String, value: String) {
("CLASS", starshipClass)
}
var item3: (label: String, value: String) {
("HYPERDRIVE RATING", hyperdriveRating)
}
var listTitle: String {
"FILMS"
}
var listItems: [String] {
films
}
}
Just like you did with Film
before, this extension allows DetailViewController
to get the correct labels and values from the model itself.
Fetching the Starship Data
To fetch the starship data, you’ll need a new networking call. Open DetailViewController.swift and add the following import statement to the top:
import Alamofire
Then at the bottom of the file, add:
extension DetailViewController {
// 1
private func fetch<T: Decodable & Displayable>(_ list: [String], of: T.Type) {
var items: [T] = []
// 2
let fetchGroup = DispatchGroup()
// 3
list.forEach { (url) in
// 4
fetchGroup.enter()
// 5
AF.request(url).validate().responseDecodable(of: T.self) { (response) in
if let value = response.value {
items.append(value)
}
// 6
fetchGroup.leave()
}
}
fetchGroup.notify(queue: .main) {
self.listData = items
self.listTableView.reloadData()
}
}
}
Here is what’s happening in this code:
- You may have noticed that
Starship
contains a list of films, which you’ll want to display. Since bothFilm
andStarship
areDisplayable
, you can write a generic helper to perform the network request. It needs only to know the type of item its fetching so it can properly decode the result. - You need to make multiple calls, one per list item, and these calls will be asynchronous and may return out of order. To handle them, you use a dispatch group so you’re notified when all the calls have completed.
- Loop through each item in the list.
- Inform the dispatch group that you are entering.
- Make an Alamofire request to the starship endpoint, validate the response, and decode the response into an item of the appropriate type.
- In the request’s completion handler, inform the dispatch group that you’re leaving.
- Once the dispatch group has received a
leave()
for eachenter()
, you ensure you’re running on the main queue, save the list tolistData
and reload the list table view.
Now that you have your helper built, you need to actually fetch the list of starships from a film. Add the following inside your extension:
func fetchList() {
// 1
guard let data = data else { return }
// 2
switch data {
case is Film:
fetch(data.listItems, of: Starship.self)
default:
print("Unknown type: ", String(describing: type(of: data)))
}
}
Here’s what this does:
- Since
data
is optional, ensure it’s notnil
before doing anything else. - Use the type of
data
to decide how to invoke your helper method. - If the data is a
Film
, the associated list is of starships.
Now that you’re able to fetch the starships, you need to be able to display it in your app. That’s what you’ll do in your next step.
Updating Your Table View
In tableView(_:cellForRowAt:)
, add the following before return cell
:
cell.textLabel?.text = listData[indexPath.row].titleLabelText
This code sets the cell’s textLabel
with the appropriate title from your list data.
Finally, add the following at the end of viewDidLoad()
:
fetchList()
Build and run, then tap any film. You’ll see a detail view that’s fully populated with film data and starship data. Neat, right?
The app is starting to look pretty solid. However, look at the main view controller and notice that there’s a search bar that isn’t working. You want to be able to search for starships by name or model, and you’ll tackle that next.
Sending Parameters With a Request
For the search to work, you need a list of the starships that match the search criteria. To accomplish this, you need to send the search criteria to the endpoint for getting starships.
Earlier, you used the films’ endpoint, https://swapi.dev/api/films, to get the list of films. You can also get a list of all starships with the https://swapi.dev/api/starships endpoint.
Take a look at the endpoint, and you’ll see a response similar to the film’s response:
success({
count = 37;
next = "<null>";
previous = "<null>";
results = ({...})
})
The only difference is that this time, the results data is a list of all starships.
Alamofire’s request
can accept more than just the URL string that you’ve sent so far. It can also accept an array of key/value pairs as parameters.
The swapi.dev API allows you to send parameters to the starships endpoint to perform a search. To do this, you use a key of search
with the search criteria as the value.
But before you dive into that, you need to set up a new model called Starships
so that you can decode the response just like you do with the other responses.