Veronika Babii
Veronika Babii

Reputation: 384

Display array elements from JSON in the tableview

I create a request to CocktailDB API and get cocktails' categories from JSON output, then I add all cocktails' categories to an array.

I want to display elements from an array in my tableview,
but tableview is empty and categoriesArray.count return 0.

My code:

class ViewController: UIViewController {
    
    struct Categories {
        let categoryName: String
    }
    
    @IBOutlet weak var tableView: UITableView!
    var categoriesArray = [String]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        getCategories()
    }
    
    func getCategories() {
        let url = URL(string: "https://www.thecocktaildb.com/api/json/v1/1/list.php?c=list")!
        
        let session = URLSession.shared
        
        let task = session.dataTask(with: url) { (data, response, error) in
            do {
                let jsonData = try JSONSerialization.jsonObject(with: data!, options: []) as? [String: Any]
                let output = self.jsonParserCategories(jsonData!)
                
                self.categoriesArray.append(contentsOf: output)
                print(self.categoriesArray) // print out an array of categories

            } catch {
                print(error)
                return
            }
        }
        task.resume()
    }
    
    private func jsonParserCategories(_ data: [String: Any]) -> [String] {
        var categArray: [String] = []
        
        let allDrinks = data["drinks"] as! [Any]
        
        allDrinks.forEach {
            categArray.append(($0 as! [String: Any])["strCategory"] as! String)
        }
        
        return categArray
    }
}

extension ViewController: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 2
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return UITableViewCell(style: .default, reuseIdentifier: "cell")
    }
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return categoriesArray.count // return 0 
    }
    
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return categoriesArray[section]
    }
}

JSON structure: enter image description here

Upvotes: 1

Views: 78

Answers (2)

Frankenstein
Frankenstein

Reputation: 16361

You've to call reloadData after the data is set. Also, set the array to empty at the beginning of the getCategories method.

func getCategories() {
    categoriesArray = [] // set array to empty
    //...
    self.categoriesArray.append(contentsOf: output)
    DispatchQueue.main.async {
        self.tableView.reloadData() // call reload once `categoriesArray` is set
    }

Add-on: Use Codable model to decode JSON instead of JSONSerialization.

Upvotes: 0

Jawad Ali
Jawad Ali

Reputation: 14417

Reload your table data once you get response

func getCategories() {
        let url = URL(string: "https://www.thecocktaildb.com/api/json/v1/1/list.php?c=list")!
        
        let session = URLSession.shared
        
        let task = session.dataTask(with: url) { (data, response, error) in
            do {
                let jsonData = try JSONSerialization.jsonObject(with: data!, options: []) as? [String: Any]
                let output = self.jsonParserCategories(jsonData!)
                
                self.categoriesArray.append(contentsOf: output)
                print(self.categoriesArray) // print out an array of categories
                DispatchQueue.main.async {
                    tableView.reloadData()
                  }

            } catch {
                print(error)
                return
            }
        }
        task.resume()
    }

Upvotes: 0

Related Questions