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
    }
}
vadian
  • 274,689
  • 30
  • 353
  • 361
  • 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? – SWAT Dec 22 '19 at 08:15
  • `RootResults` one or more property type not match – Nazmul Hasan Dec 22 '19 at 08:18
  • Please add the structs and elaborate **what** exactly does not work. – vadian Dec 22 '19 at 08: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? } – Ammar Alshuaibi Dec 22 '19 at 11:48
  • i can access results array but commodities array i cannot – Ammar Alshuaibi Dec 22 '19 at 11:51
  • http://abuseedotrading.com/apps/api/acp/?key=4ea1e08dd9ab329bbdaa9e5b42939c04&query=list_containers you can check my API because this is the time I programming in swift language – Ammar Alshuaibi Dec 22 '19 at 11:53
  • Failed to decode JSON: keyNotFound(CodingKeys(stringValue: "commodities", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"commodities\", intValue: nil) (\"commodities\").", underlyingError: nil)) – Ammar Alshuaibi Dec 22 '19 at 11:55
  • The JSON at the given URL does not cause this decoding error. And please name structs with starting capital letter. – vadian Dec 22 '19 at 12:29

1 Answers1

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