Fetching data from API, passing to view Controllers using completion handlers and populating data in UITableView using Swift

Sidhdesh Vadgaonkar
15 min readJun 27, 2020

--

Let me first give an overview of how are we going to perform this operation, initially we will setup the UITableView, then we will create a model which will be responsible for holding the data to be viewed on table, then we will create another class which will fetch data from API in the form of JSON, store it with the model which was created earlier, and send it to view controller and this view controller will be responsible for providing data to the table view. The bottom line is we will follow MVC Pattern here.

The API which I am using here, provides me with car park space data, which includes location of the car park, along with some other details regarding it. For more open source API please visit Open data Melbourne. Let’s begin….!!!

Setting up the UITABLEVIEW

Let’s start by creating a new project in XCode, give any name you want, let’s do this, create a new “Single View App” project,

Before you will be a storyboard of the project and now let’s start by adding a UITableView on the storyboard, just search for the UITableView Control in the “Object Library” (It is provided by XCode, which holds all the UI Controls).

(Note: XCode, provides a lot of updates and so the location of the “Object Library” button keeps on changing), I will ease your work, in latest version of XCode you will find the button for opening object library, above the “Inspector Panel” and to the right of “Show or Hide Code Review” button. Please refer to the image below)

Now, just search for “UITableView” control in the Object library, and just drag and drop it on the storyboard view, please refer to the image below

Added UITableView on storyboard

View Controllers

In a storyboard, a scene represents one content screen which corresponds to one single view controller. View Controller is a vital part of any IOS Application, each and every IOS application has one or many view controllers, these controllers are connected to the UI, they act as a bridge which provides data to UI from data models.

A view controller consists of one parent view which has many more sub views, like in above example UITableView is the sub view of the parent view. Now the user interactions with this UITableView will be handled in the parent’s view controller.

Apple has provided a UIKit which provides several standard view controllers, these include for navigation and for managing specific type of contents. Some examples of most used view controllers provided by Apple are UIViewController, UITableViewController, UICollectionViewController, UINavigationController, UISearchController etc.

Now, the way to create a view controller in swift is easy, just follow the steps given below

On the toolbar, there is file option, click it then choose New — File, a tab will pop down which will ask to choose template for the new file, select the file type as Cocoa touch class in the Source category and click “Next”. Please refer to the image given below

Step 1 for creating ViewController

Now in the next window, it will ask to name the new view controller file to be created, give it a name for example “ViewController”, select the subclass as “UIViewController”. There is no need to create XIB file so don’t tick the checkbox and keep the language as swift, and then click “Next”. Please refer to the image below

Step 2 for creating ViewController

The final step, here you will be asked the location where you want to place the file, if you have some place reserved, just choose the location or don’t do anything and just click “Create”, it will get created in the default location.

Final step for View Controller Creation

Connect UI to Source Code

We have, created our very own custom view controller class, which is derived from the UI View Controller, the next step is connecting the scene containing the “UITableView” to this custom view controller. This connection is important as we need the behaviour that we defined in the code to be on the UI. The way of connecting the view controller subclass to view is easy, please follow the given steps below.

  1. Open the main storyboard Main.storyboard file
  2. Then click on the “view controller icon”, which occurs on the top of the storyboard screen. Please refer to the image below, focus on the section which is highlighted by white square that is the view controller icon.

3. Now expand the Inspector panel by clicking on the button “Hide or Show Inspector panel” (I have mentioned its location above). When the panel expands, you will see by default identity inspector is selected and below it there is a tab “Custom Class” which holds an option “Class”, please enter the name of your custom view controller, in our case it is “ViewController” and just press “enter” key, please refer to the image below.

Outlets

Well speaking of outlets, these are references to the UI Objects, inside the view controller. In a simpler way, “Outlets are connection between UI elements and the code in the view controller”. In short, there must be a code in the view controller that must talk with the view, and outlet is a way through which we can talk to with the UI elements and make them work as we want. For example, if you created a button on UI and you want to change its colour on click, first thing you need to do is create a connection(outlet) of this button with the view controller. Now there will be some code in the view controller which will change the colour of the button.

Now as per our project, we have added a UITableView on the storyboard and now we need an Outlet for this table view, so that we can communicate with the table on the storyboard.

To connect the Table View with the view controller,

Open the main storyboard Main.storyboard

Now click on the adjust editor options which is at the rightmost top below “Show and Hide Code Review” button and choose “Assistant”, this will display the view controller.swift file to the right( this is the view controller .swift file which is connected to your parent view)

Most of the times the XCode window is crowded, so if you feel that you need some more space to work, just collapse project navigator, debug area and utility panel, by clicking on three buttons which are at the rightmost top just besides the“Show and Hide Code review” button.

Now you are ready to work, now in the view controller find a line which starts with the keyword class.

Now below this class line we need to create an outlet, now in your storyboard select the “UITableView”, control drag from the “UITableView” on the view controller, and stop the drag below the class line, as you drag, you will be able to see a white line, if there is no white line then the way you dragging is not proper, you will see a line like this,

When you get a line starting with “@IBOutlet” this means that the outlet has been created successfully. Now using this outlet, we can communicate with the table view.

The table view has been created, the table is just responsible for presentation of data, but what about the data? Who is responsible for managing the data to the for the table view? Here the “UITableViewDataSource” comes into picture.

UITableViewDataSource

For managing the data, we assign table with a data source object and this object is of the class who implements this protocol. With the help of this data source, we could tell about the number of rows or sections in the table, provide cells for each row in the table with data, provide titles for header sections and many more.

Let’s see how are we going to use this protocol in our project, according to description which is given above, the table view needs a data source, until now, we have only one class ViewController.swift and there is going to be another class which is going to fetch data from API and give it to view controller, and the view controller will provide data to the table view, so it completely makes sense that the “View Controller” class which we created must act as source of data, so the view controller class needs to implement this protocol, please refer to the image below

Implementing Data Source protocol

After inhering the “UITableViewDataSource”, you will be asked to implement two different functions so that the View Controller conforms to the data source protocol, please refer to the image given below

two functions after implementing UITableDataSource

There are two functions provided by the data source protocol, the first function is responsible for returning the number of rows in the table and the the second function is responsible, for returning the cell for the row with some data

(Note: Currently, keep these methods, as it is, we are going to write some block of code here afterwards)

This is the end of First Section, I hope you all understand the process of setting up the UITableView. Now lets see how to create a model that will hold the data from the API

Setting up the Model

As we are following the MVC pattern, now it’s time to create the model which will hold our data, according to the API which I am using we have total 10 fields, please follow the steps which are given below for constructing a model

Create a new folder with name “Model”, “Right click” on this folder and choose option new file, you will get a pop down which will ask you for the type of file to be constructed, this time we need a swift file, as we need to create custom structure, that is responsible for holding data, click the “Next” button ,give the name for the file, for example “CarPark” and then click “Create”, Now as I said earlier, my API has total ten fields, so let’s create a struct which implements a protocol “Codable” in the newly created file. The last field has two more fields inside it and so we need to create another struct which again implements “Codable” which will hold these fields, please refer to the image below

CarPark Model

As I said above, the last field, in the above picture “geocoded_column” contains two sub fields and so I created a struct with name “GeocodedColumn” which holds the two sub fields “type” and “coordinates”.

I don’t know, how many of you have recognized it, but the variable names in this struct doesn’t follow the camel Case, now why is that …?

Please look at the highlighted parts of the images given below,

Data in Json format from web API
Model class for storing data

Most of the things would be clear now, the first image is the data in the json format which is hosted on the API and the second image is the model which is going to hold the data, the json file consist of key value pairs, remember that the “variable names in the model must be same as the keys in the json file”, or else the json decoder will never recognise that the fields correspond to keys in json file.

Now, what is Codable?

Codable

Codable protocol is used for encoding and decoding some custom data formats, in our case the custom data format is JSON. Just by implementing the codable protocol, we can map Json objects to swift and vice versa.

Before Codable protocol came into picture, the process which was needed to follow for getting data was garrulous, you manually had to serialize the json and then type cast this data to suitable swift type, this system works, but if your json contains a lot of data then you need to serialize everything, moreover it is very hard to catch some errors and type inconsistency.

When codable came into picture there was no need to follow the big process which is given above, just implement the codable protocol and that’s it, the encoding and decoding is in your hands now. The Codable protocol is combination of two other protocols “Encoder” and “Decoder”. There are two classes namely “JsonEncoder” and “JsonDecoder” which implement these protocols and help to encode or decode json. We will look into these classes as we go further.

Fetching data from Web Api

Fetching data from web API is one of the important skills of an IOS developer, previously people used third party frameworks for fetching data from web API, but after the introduction of “Codable” in swift 4, fetching data from web API has become quite easy. Swift provides a very nice and easy way and so there is no reason to use third party frameworks.

For fetching data from web API, we need to learn some of the important concepts like,

Completion Handlers

URLSession

Completion Handlers

In simple words, completion handler is closure, or you can say a block of code, which can be passed to a function and then called when that function execution is finished. They are used to pass data from one class to another.

The completion handlers ae mostly used when we know that the function will take some time to execute. It is used when people don’t want to pause their work, while performing a time-consuming operation. For example, with the API calls, an URL request is been sent by us to server requesting some data. Instead of making ourselves wait for the reply from server we will create a completion handler, and this means that we tell our application to do some other work like loading the rest of the page, till the response is received from server.

The completion handler will notify the application once it has all the information we asked for, it will contain all the data which can be sent to the view controller which will then send it to the table view.

Let me give an overview, we are going to use completion handler to pass the data which we get from API to the view controller,

Now with the help of code let’s see how we setup the completion handler.

Create a normal swift file, and name it as “FetchData”, the steps for creating a normal swift file are already given above, now create a function “fetchData”, which will show how the completion handler is passed to the function and also tell about call to the completion handler

The first line in the picture above, shows how a completion handler is passed to the function with parameters, in our case we are passing the array object of the model class, we have created array object of model class because we are going to store all the json data using this model. On the last line we are passing the desired variable to the completion handler, this is call to the completion handler, when the function gets executed.

URLSession

The URL Session is used to create a task which is called URLSessionTask which is used to fetch data from the API. The URL Session provides us with dataTask, in simple words dataTask creates a task which is responsible for retrieving data from the specified URL. The dataTasks are usually provided with different type of information, it also contains a completion handler, which will always return same type of information: data, response, error.

Let’s start with error, it may happen that the dataTask may throw error, knowing about the error will be priority as then we can perform necessary operations to prevent the application crash, or direct the flow of the application in another direction.

The dataTask can also receive response which can be converted into http response, in this way we can monitor the status codes and understand the situation, for example 202, OK, which means everything is going well.

For the data, we will use the “JsonDecoder” which will decode the json, for this purpose there must be a model constructed and fortunately we have created one namely “CarPark”.

Now let’s see how we should use URL Session in our code to fetch data from API, please refer to the image below

Please refer to above image, on line number 20, “URL.init” function checks whether the URL is valid one, you will also find a variable “urlForFetchingData”, this contains my URL i.e. the path to the json file on internet, for example “https: google/myApi/myfile.json”. On line number 22, I have created a dataTask, and passed the URL, along with completion handler having parameters: data, response, error as we discussed above. On line number 24, I have checked for errors or data being null, if such thing happens I have just printed that there is an error, else I have used “JsonDecoder” and then passed my model into it and then got the array of CarPark objects which is stored in the variable “carParkSpaces”, this is the step(line 33) where we get the data from API, now as the function has completed its execution, it’s time to call completion handler and pass the “carParkSpaces” as argument to it.

Until now, we have set up the TableView, created the model and fetched data from API, now the final step is to show this data on the Table View using the view controller.

Displaying data on the Table View

Now, move on to the custom View Controller that we created, create object of “FetchData” class and array object of model class “CarPark”

The next step is to get data that was fetched from API, so with the help of “fetchData” object call the method “fetchData”, remember that when we call the method “fetchData” it will start its execution, and after execution it will call the completion handler, so in the view controller the completion handler is going to be called, please refer to the code below to see how should we call the completion handler.

Please refer to the image above, here what happens is that we get data in the form of array from completion handler and then we assign it to object that we created “carParkSpaces” in the view Controller, and don’t forget to assign the data source for table view(please refer to the last line in above image).

Now we have all the data that we got from API, into the object that we created “carParkSpaces”, now it’s time to display data from this array on the table view, if you remember we have two functions , that we got when we inherited “UITableViewDataSource”, these functions will now help us to tell table about total number of rows and the data that needs to be displayed for each cell, please refer to below image

The first function, will return total number of rows in the table which will be equal to the array count, and the data that’s need to be stored on the cell, is communicated by second function, where we change the text of the cell, according ot the data in the array, currently we are just showing the street name.

Now, everything is done and dusted, but if you start your application, you will find no data, so why is that…?, it is because, in order for the data to be shown on the table, the table view must reload itself when the view controller receives data from API. If you go on step number 2, you will see that , at that step we get data from completion handler and assign to the “carParkSpaces” variable, and we are using this variable for setting data for the table view, in simple words, we need to reload the table once, the “carParkSpaces” variable is set, in order to do that please refer to the image below

Now, as you might have guessed, I have used the “didSet” property of the variable, as a signal to reload the table, so at step number 2 when the variable will be set, this “didSet” code block will be called and .. you can see all the data on the table…

The data from API is displayed on table

--

--