0

I'm trying to parse API JSON and display it in UITableView, but the problem is I cannot access all array in this API.

struct RootResults: Codable { 
    var results: [results] 
} 

// MARK: - results 
struct results: Codable { 
    var container_number: String? 
    var commodities: [commodities] 
} 

// MARK: - commodities 
struct commodities: Codable { 
    var commodity_name_en: String? 
    var varieties: [varieties] 
} 

// MARK: - varieties 
struct varieties: Codable { 
    var variety_name_en: String? 
    var variety_name_ar: String? 
} 

import UIKit

class ViewController: UIViewController {

    @IBOutlet var resultsTable: UITableView!
    override func viewDidLoad() {
        super.viewDidLoad()
        abuseedoAPIget() 
    }

    var arrData = [results]()
    var arrResults = [commodities]()
    func abuseedoAPIget(){
        let urlJSON = "http://abuseedotrading.com/apps/api/acp/?key=4ea1e08dd9ab329bbdaa9e5b42939c04&query=list_containers"
            guard let url = URL(string: urlJSON) else {return}
            URLSession.shared.dataTask(with: url) { (data, response, error) in
                guard let data = data else {return}
                guard error == nil else {return}
                do {
                    let decoder = JSONDecoder()
                    let APIResponse = try decoder.decode(RootResults.self, from: data)
                    self.arrData = APIResponse.results
                    DispatchQueue.main.async{
                        self.resultsTable.reloadData()
                    }

                } catch let error {
                    print("Failed to decode JSON:", error)
                }
            }.resume()
        }

}

extension ViewController: UITableViewDelegate, UITableViewDataSource{

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {    
        return arrData.count     
    }


    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell

        let dataa = arrData[indexPath.row]
        cell.conLabel.text = dataa.container_number
       cell.comLabel.text = dataa.commodity_name_en
        return cell
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

        return UITableView.automaticDimension
    }
}
8
  • Give more info on your log. What does it say? Do you have null pointer exceptions? Have you added the AppTransportSecurity in your info plist? Commented Dec 22, 2019 at 8:15
  • RootResults one or more property type not match Commented Dec 22, 2019 at 8:18
  • Please add the structs and elaborate what exactly does not work. Commented Dec 22, 2019 at 8:21
  • import Foundation // MARK: - RootResults struct RootResults: Codable { var results: [results] } // MARK: - results struct results: Codable { var container_number: String? var commodities: [commodities] } // MARK: - commodities struct commodities: Codable { var commodity_name_en: String? var varieties: [varieties] } // MARK: - varieties struct varieties: Codable { var variety_name_en: String? var variety_name_ar: String? } Commented Dec 22, 2019 at 11:48
  • i can access results array but commodities array i cannot Commented Dec 22, 2019 at 11:51

1 Answer 1

1

For Swift to be able to decode the JSON response into objects you need to have a similar structure defined in Swift using objects.

Your RootResults object needs to implement Codable protocol and represent the JSON structure.

Below a part of the returned JSON:

{
  "status": 200,
  "runtime": 1.7315270900726,
  "results_count": 13,
  "results": [
    {
      "container_id": 36473,
      "container_number": "MMAU1163814",
      "shipment_id": 17359,
    }
}

RootResults would look something like this:

struct RootResults: Codable {
  let status: Int
  let runtime: Float
  let results_count: 13
  let results: [Container]
}

struct Container: Codable {
  let container_id: Int
  let container_number: String
  let shipment_id: Int
}

More information on Swift Codable

Swift codable

SO question about

In the function tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) you are accessing data on different levels. The container_number -property is accessible when retrieving an object from results. The commodity_name_en is a "level" deeper and part-of the commodities -array. To access the first item in the commodities -array , try the following:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell

        let dataa = arrData[indexPath.row]
        cell.conLabel.text = dataa.container_number
       cell.comLabel.text = dataa.commodities[0].commodity_name_en
        return cell
    }

As Vadian mentions, it's common to start types(struct, class, enum) with a capital letter in Swift. Have a look at struct and classes documentation

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much Eelco, now I can access all levels in my API. the last hint working properly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.