iOS Networking - APIs & JSON Parsing Made Easy
By: Harun Güneş
Tags: iOS, Mobile App Development, Apple, Swift, Programming

Make sure that you understand the structure of the application.

Create a Swift file called CovidAPI in Model group and type or copy/paste below:

struct CovidAPI { static let address = "https://disease.sh/v2/countries/"

}

We use “static variable” so that we don’t need to initialize the CovidAPI object for later use. We have direct access to “address” variable in any file as “CovidAPI.address”.

In order to list country names in our tableView, we need to parse JSON data.

Create a Swift file called CountryModel in Model group. This file will include the data which we are going to use to parse our JSON file. JSON parsing requires the data to include Encodable and Decodable protocols. Swift has a TypeAlias that includes both of them: “Codable”.

Pay more attention that variable names in CountryModel file and keys in the JSON file are matching.

Let’s start fetching the data and using it in our app.

In our CovidAPI file, we initialized the address variable as a string. But we can’t use the string as a link, it must have “URL” data type.

In our ViewController class there is viewDidLoad() function. Inside this function, let’s make the address string a URL.

let addressUrl = URL(string: CovidAPI.address)

URL() is a predefined function in Swift. It takes a string as an argument and returns it as a URL.

Now that we have a new variable called “addressUrl” and its data type is URL.

Create URLSession

In our viewDidLoad() function let’s start parsing the JSON data.

Firstly, create a URL session. All we need is to use the URL and create a “dataTask” with “completionHandler” (data, response, error) to parse the JSON data.

let task = URLSession.shared.dataTask(with: addressUrl!) { (data, response, error) in }

Make sure that there is no error with the “guard” statement.

guard let data = data else {

print("Error1: \(error!)")

return

}

So it looks like:

let task = URLSession.shared.dataTask(with: addressUrl!) { (data, response, error) in guard let data = data else {

print("Error1: \(error!)")

return

} }

We use the “guard” statement to trigger the action in certain conditions. If it doesn’t pass the statement, the rest won’t be compiled and it will return.

In order to decode the data from CountryModel, let’s create a “JSONDecoder” object just below the guard statement.

let decoder = JSONDecoder()

And now take a look at the below code:

We are creating a “country” object by decoding the “CountryModel” with its attributes which are country names, flags, and daily & total statistics and we are iterating them over to append into lists by the “for” loop. For this, we need to declare those lists as global variables in ViewController class in order to have access from everywhere.

var countryNames: [String] = []

var flags: [String] = []

var totalCaseList: [Int] = []

var totalDeathList: [Int] = []

var totalRecoveredList: [Int] = []

var dailyCaseList: [Int] = []

var dailyDeathList: [Int] = []

var dailyRecoveredList: [Int] = []

You can place these variables just below:

@IBOutlet weak var listView: UITableView!

For tableView, we are going to add an extension to use UITableViewDelegate and UITableViewDataSource protocols just below the ViewController class.

extension ViewController: UITableViewDelegate, UITableViewDataSource {

}

In this extension, we are going to make our tableView work.

Firstly, the below function will tell tableView how many rows it should have.

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

return countryNames.count

}

Naturally, we are going to have as many rows as country items.

The below code will push the data to be seen in tableView cells. (Names of countries)

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = UITableViewCell()

cell.textLabel?.text = countryNames[indexPath.row]

return cell }

We have created an extension to use UITableViewDelegate and UITableViewDataSource, but we didn’t tell which tableView to assign. Include the below lines just under the super.viewDidLoad() function to complete the assignment to tableView itself.

tableView.delegate = self

tableView.dataSource = self

The last thing for this section is to include the below code after the closing bracket of for loop to prioritize and reload the tableView data.

DispatchQueue.main.async {

self.tableView.reloadData()

}

Your ViewController file will look like:

Let’s run the app.

As you can see, our application is now working and we can see the country list in our tableView. Let’s head into the next section to make tableView cells clickable and show the current statistics for the chosen country.