Alamofire: A Quick Guide

Furkan Can Baytemur
Orion Innovation techClub
9 min readMar 31, 2023

In your mobile development journey, you will surely encounter some apps that require you to make network requests. Network requests are a crucial step in improving your knowledge of mobile development. If you are an iOS developer like me, then you need to learn Alamofire to make your network requests.

Elegant Networking in Swift

As their motto says, Alamofire makes network requests as gracefully as possible. It is written with Swift for meeting the needs of iOS developers. It can also be used for macOS if the application is powered by Swift. Providing a clean and elegant API, Alamofire is a popular tool to handle HTTP requests. You can easily make asynchronous network requests, upload and download files, and integrate with OAuth and other authentication mechanisms.

Photo by Fernand De Canne on Unsplash

In addition to its elegance, Alamofire is very flexible. It can be used in a simple app like a weather app or a complex app like inventory tracking for a company.

In this article, we will be making a simple movie application to see how to install Alamofire and make network requests with it.

Installing Alamofire

There are many ways to install Alamofire to your project like Carthage and Swift Package Manager. In this article, we are going to focus on CocoaPods.

First of all, create a new iOS project in XCode. Don’t forget to choose SwiftUI as the Interface option. Before writing any code to our project, let’s add Alamofire as a Pods package. Open your project folder in Finder. You should be seeing the project folder and xcodeproj file. Here, open a terminal page and write this command to initiate Cocoapods.

pod init

Now you will see a new file named Podfile. Open it in a text editor and add Alamofire like this:

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'AlamoMovie' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!

# Pods for AlamoMovie

pod 'Alamofire'

end

Since we can use the latest version, we didn’t include a version number for Alamofire. After saving the file, write this command to the terminal to install Pods project with Alamofire.

pod install

After installation is completed. You will see new files added to the project. The important one is xcworkspace file. Having installed Cocoapods, you need to close your Xcode project and open the workspace file since there is a new project named Pods.

When you open the workspace file, you need to see a project structure like above. Check that Pods folder has Alamofire in it. We have installed Alamofire successfully. Let’s continue with designing our UI.

Designing our App

In this app, we will list the top-rated movies of all time by. Our UI will be designed with SwiftUI and show a list of components that will feature the main properties of a movie. Firstly, let’s design our movie cell.

For designing this component, we need variables for a title, release year, rating and motto of the movie.

struct MovieCell: View {
let title : String
let rating : Int
let ratingColor : Color
let motto : String
let imageURL : String

init(title: String, year: String, rating: Int, motto: String, poster: String) {
self.title = "\(title) (\(year))"

self.rating = rating
self.ratingColor = rating > 79 ? Color.green : rating > 49 ? Color.yellow : Color.red

self.motto = motto
self.imageURL = poster
}
}

We have an additional variable named ratingColor. It will be used to change the color of the rating text based on the formula written in the init function. We only have the URL of the image, we will be rendered as an image using the AsyncImage struct which is introduced in iOS 15.

var body: some View {
HStack {
AsyncImage(url: URL(string: imageURL)) { image in
image
.resizable()
.aspectRatio(contentMode: .fit)
} placeholder: {
Color.gray
.frame(width: 100)
}

VStack(alignment: .leading) {
Text(title)
.font(.title3)
.fontWeight(.medium)

Divider()

HStack {
ZStack {
Circle()
.stroke(ratingColor, lineWidth: 4)
Text("\(rating)")
.foregroundColor(ratingColor)
}
.frame(height: 30)

Text(motto)
.font(.callout)
.italic()
}
}
}
.frame(height: 150)
.frame(maxWidth: .infinity, alignment: .leading)
}

We place our components in a HStack to place them horizontally to each other. The first component is the poster of the movie which is placed with AsyncImage struct. We convert imageURL to URL since AsyncImage constructor accepts a URL variable. We also put .resizable and fit aspect ratio to make the poster conform to the height of the cell. As a placeholder, we use gray color if the image is still loading.

After the poster, we place a VStack to list our other properties. For the title, we are using a Text component with title3 font and medium font weight. We place a divider before other elements to make the title a bit more enhanced.

For our last two elements, we use an HStack. Firstly, we are designing a rating component which is just text inside a circle. To design it, we used a ZStack and placed a circle alongside the text itself.

Lastly, we use a Text component with the italic font to showcase the motto of the movie. And, we have designed our movie cell. As the next step, let’s make the network requests to get these properties from our API.

Making Requests

We will be using TMDB to get movie features. TMDB stands for “The Movie Database”. It is an online database that provides information about movies, TV shows, and other types of content related to the entertainment industry. The database contains information about cast and crew, plot summaries, ratings, and other details related to movies and TV shows.

We will follow these steps to get our features:

  • Make a request to get top-rated movies
  • Decode request to get IDs of movies
  • Use these IDs to get more information about movies
  • Decode detailed objects to get features of the movie
let API_KEY = 
let topRatedURL = "https://api.themoviedb.org/3/movie/top_rated"
let movieDetailURL = "https://api.themoviedb.org/3/movie/"
let posterBaseURL = "https://image.tmdb.org/t/p/original"

We will be using these URLs to access the API of TMDB. You can get your API key easily by just registering to TMDB for free.

class movieList: ObservableObject {
@Published var movieList : [Movie] = []

init() {
fetchMovies()
}
}

To store movies, let’s create a class named movieList conforming to ObservableObject. We need a @Published array to refresh our UI as more movies come from the API. Before filling our movieList array, we need to get the IDs of top-rated movies in the fetchMovies() function which will be executed when we create a movieList object.

func fetchMovies() {
AF.request("\(topRatedURL)?api_key=\(API_KEY)").response { response in

guard let data = response.data else { return }

do {
let jsonObject = try JSONSerialization.jsonObject(with: data)

if let dict = jsonObject as? [String: Any], let results = dict["results"] as? [[String: Any]] {
for movie in results {
if let movieID = movie["id"] as? Int {

self.fetchMovieDetail(movieID)
}
}
}
}
catch {
debugPrint(error)
}
}
}

Firstly, we use the AF object of Alamofire to make the request. The request we need to make is composed of topRatedURL and API_KEY. It will look something like this:

https://api.themoviedb.org/3/movie/top_rated?api_key=[API_KEY]

Alamofire will make the request and return us a response object which we will decode. Before making anything, we need to check if the response object has a data member to verify it was a successful request and response has values inside it. After this verification, we can decode our response with JSON serialization.

{
page = 1;
results = (
{
adult = 0;
"backdrop_path" = "/tmU7GeKVybMWFButWEGl2M4GeiP.jpg";
"genre_ids" = (
18,
80
);
id = 238;
"original_language" = en;
"original_title" = "The Godfather";
overview = "Spanning the years 1945 to 1955, a chronicle of the fictional Italian-American Corleone crime family. When organized crime family patriarch, Vito Corleone barely survives an attempt on his life, his youngest son, Michael steps in to take care of the would-be killers, launching a campaign of bloody revenge.";
popularity = "123.415";
"poster_path" = "/3bhkrj58Vtu7enYsRolD1fZdja1.jpg";
"release_date" = "1972-03-14";
title = "The Godfather";
video = 0;
"vote_average" = "8.699999999999999";
"vote_count" = 17586;
}
);
"total_pages" = 544;
"total_results" = 10877;
}

The JSON object we get will be something like this though it will have more than one movie for sure. As you see, the object has “results” and “page” keys inside it. For our purposes, the first page would be more than enough. The important object we need to get is the values of the “results” key. We transform our JSON object to an array of String keys and Any values since values might have different types. Then, we get values with the “results” key to a variable named results. If all is successful, we got the movies to the object we need. We open a for loop in the results array. The only thing we need from this object is the IDs of movies. So we get these IDs with the “id” key. Lastly, we execute a function named fetchMovieDetail. This function will make another request to get details of each movie. Let’s examine this function.

func fetchMovieDetail(_ ID: Int) {
AF.request("\(movieDetailURL)\(ID)?api_key=\(API_KEY)").response { [self] response in
guard let data = response.data else { return }

do {
let jsonObject = try JSONSerialization.jsonObject(with: data)

if let movieDetail = jsonObject as? [String: Any] {

let title = movieDetail["original_title"] as? String
let poster = movieDetail["poster_path"] as? String
let date = movieDetail["release_date"] as? String
let motto = movieDetail["tagline"] as? String
let rating = movieDetail["vote_average"] as? Double

let movie = Movie(title!, motto!, poster!, date!, rating!)

movieList.append(movie)
}
}
catch {
debugPrint(error)
}
}
}

In here, we make another request to TMDB API to get details of the movie. We use a different URL this time:

https://api.themoviedb.org/3/movie/?api_key=[API_KEY]

After making similar arrangements and transforming the JSON object to a key-value array, we can get the details that we need. We can simply create some variables and assign them respective details we can get from the JSON object. Be sure to write the correct keys for these details otherwise it would create a blank variable. With these variables at our disposal, we can create a Movie object and append it to the movieList array. Let’s examine the Movie structure to see how we are defining our movie objects.

struct Movie: Hashable {
let title: String
let motto: String
let poster: String
let rating: Int
let year: String

init(_ title: String, _ motto: String, _ posterPath: String, _ date: String, _ rating: Double) {
self.title = title
self.motto = motto
self.poster = "\(posterBaseURL)\(posterPath)"
self.rating = Int(rating * 10)
self.year = String(date.prefix(4))
}
}

As you can see, the Movie object consists of details that we get from the API. It conforms to Hashable because it will be needed to render our List on the screen. We need some modifications for some variables.

Since API only provides the back path for the movie poster, we need to insert base URL for the poster. If you try to go to URL below, you will see the poster of The Godfather movie.

https://image.tmdb.org/t/p/original/3bhkrj58Vtu7enYsRolD1fZdja1.jpg

Similarly, we use back path of other movies to get all posters in our list. For rating, we use a little calculation. Let’s see it in an example by using The Godfather’s rating.

8.712 * 10 -> 87.12 | Int(87.12) -> 87

We multiply it by 10 to make a rating out of 100 instead of an out of 10. Then, we convert it to an integer to get rid of decimal points. Lastly, We only get the first 4 characters of the date to only extract the year.

"1972-03-14".prefix(4) -> "1972"

We are almost done. We made all the requests to our API and saved them in an array. Let’s add our last code to ContentView to complete our app.

struct ContentView: View {
@ObservedObject var movies = movieList()

var body: some View {
VStack {
List {
ForEach(movies.movieList, id: \.self) { movie in
MovieCell(title: movie.title, year: movie.year, rating: movie.rating, motto: movie.motto, poster: movie.poster)
}
}
}
}
}

As we defined our array as @Published, we create our movieList object as a @ObservedObject to enable the app to track our object as it updates. In the body, we define a VStack for our baseline. Then we just create a List and render our MovieCell elements with a ForEach method. This ForEach method will be based on our movieList array and it will be updated as our array is updated with requests from the API.

And, we’re done! We have created a simple movie application. You can scroll in the app to see more movies below.

I hope you understood how to make requests in Alamofire. The process is very similar for other APIs as well. If you need something else, don’t forget to check out the documentation of Alamofire.

If you have any questions, you can reach me on LinkedIn

Until next time…

--

--