10.6. Fetching Data with AlamoFire: GET
http://apis.sakibnm.work:8888/contacts/text/getall
It's time to fetch the contacts' names and display them in our table view. We will call the API with getall endpoint when the app starts, and display the response on the table view (10.3. Testing our Simple Custom API with Postman).
Using Alamofire for text responses
If you noticed, in our API, we are getting back text responses from the server. We will use Alamofire to process the responses. Before we do, let's define an array of Strings in our ViewController for populating the table view. That array will hold the names of the contacts returned by the API endpoint getall.
//
// ViewController.swift
// App10
//
// Created by Sakib Miazi on 5/25/23.
//
import UIKit
import Alamofire
class ViewController: UIViewController {
let mainScreen = MainScreenView()
//MARK: list to display the contact names in the TableView...
var contactNames = [String]()
//codes omitted...
}
First, we need the API base URL to be set up. You can directly use the URL string in the call; however, it is always a better practice if you save these API details in a separate file as a static String, so that you can reuse that from any screen if you need to.
Let's create a file named APIConfigs.swift under App10 folder. It is a Swift class file, not a CocoaTouch Class.

In APIConfig.swift, let's add the static constant for the base URL:
You can access the base URL by writing APIConfigs.baseURL from anywhere in the project.
The 'getall' endpoint with Alamofire
Now, let's write a function to call the getall API endpoint and load the names in contactNames array.
First of all, you need to import the Alamofire library.
Let's look at the function getAllContacs() method definition:
First, we build the URL with the
baseURLand thegetallendpoint using URL() initializer. URL() returns a URL wrapped with optional (in case it cannot create a valid URL, it returns an Optional(nil)). We have to unwrap it. So we unwrap it and put it in the constanturl.Then we use
urlto make a request with Alamofire. We useAFto use Alamofire functions. So, here we are creating an Alamofire request with theurlwe built.If you noticed, we set the method of the request to
.get. Remember,getallendpoint of the API server expects a GET request.Then we call the
responseString()method for the request. We are handling text responses, right? So, we need to catch String-type data from the response we get from the server.Then we write a closure
completionHandlerto deal with the data after we receive the response. Please note any communication over the Internet is Asynchronous. That means we are dealing with data that are hosted probably hundreds if not thousands of miles away. So, it will take time to receive the response from the server after you send the request. It might feel like it's real-time, but logically, it's not. So, when we build apps that communicate over the Internet, we must be very careful dealing with it. We should not expect that we will receive the response right away.In the closure, we print
response.resultto see what kind of data we received as the response. If you run the app now, It prints something like this:success("Alice Smith\nBob Smith\nDavid B\nAlex C\nMark W\n")success()in the response means the request was successfully transmitted, and there was no network error.See, we have in between two consecutive names. The character means a new line. So, we have to fetch the whole String and then use it.
Also, the status code the response has is very important. We need to check if it is a 200-level or a 400-level code.
200-level codes mean the request was valid, and we received a desirable response.
400-level codes mean the request was incorrect, so we must handle the response appropriately to manage the UI elements properly.
So, let's write the following code in the completionHandler closure taking care of the status codes and network errors:
In the above code:
First, we retrieve the status code from the response (at line 6). It is an optional value. So, we need to unwrap it when we use it.
Then we check for network errors from
response.result. (At line 8).If there is no network error, we now check if the status code is a 200-level- or 400-level.
If the code is a 200-level code:
Then we separate each line by splitting the data using the delimiter . (At line 17).
Then we set the Strings from data to
contactNamesarray.And then, we print the array.
If the code is 400- or 500-level, we print the debug log for now. You might want to handle these conditions depending on the app's needs.
We might need to check our internet connection if there is a network failure. (at line 36).
Now, if we run the app, it will run, but you won't see any items printed. If you check the outputs, you might see something like the following:
By default, iOS does not allow HTTP connections without encryption. We should always use the connections through HTTPS.
However, since my API is a dumb API, and I am using the API for demonstration purposes, I didn't go through the HTTPS configuration process. So, we need to enable unencrypted HTTP connections in our app.
If you face this, you can solve this by doing the following:
Enabling unencrypted HTTP in our app
We need to open
Info.plistfile from the File Navigator of the project.Right-click (control + click) on the empty space of
Info.plist.Select
Add Row.Search and Select "App Transport Security Settings."
Inside "App Transport Security Settings," add an attribute by clicking plus icon(
+).Set "Allow Arbitrary Loads" attribute's value to YES.

It should now allow unencrypted HTTP.
If we run the app now, it should print the following:
["Alice Smith", "Bob Smith", "David B", "Alex C", "Mark W", ""].
Interestingly, there is an empty String at the end. This happens because the server adds a character at the end of the last user's name. So we need to remove it from the contactNames.
Let's add self.contactNames.removeLast() after line 18.
Now, we have the perfect contactNames array to be displayed in the table view.
Displaying data on the table view
Now, let's adopt the protocols for the table view:
Then, set the delegate and data source in viewDidLoad() method.
In the above code, at line 11, we remove the separator line of the table view. If you want to remove the line, you get to do this after the table view is populated. If you add this instruction when setting up the table view, it will not work. So, we write this code in the controller.
If you run the app now, the table view remains empty. As I discussed before, the internet calls are asynchronous. So, we need to wait until the response is received. Once we receive the response, we should reload the data for the table view. Hence, we add the following line into getAllContacts() method after we remove the last element from contactNames: self.mainScreen.tableViewContacts.reloadData().
The final getAllContacts() method looks as follows:
Let's run the app again. It should look like this:

Last updated
Was this helpful?