Fill UITableviewcells from JSON

Hey all,

I want to fill an UITable with data from a json request. When i create a static table with predefined values i get a response just fine but when i use the json response i get no output in my table. I can print the values just fine so my json request works.

This is my code

struct Todolist: Codable {
let todo: [Todo]

}

struct Todo: Codable {
let id: String
let title: String
let done: String
}

class CompetencesController: UITableViewController {

let cellID = "cellID"

var list = ["I", "Dont", "Get", "It"]
var show: [AnyObject] = []


override func viewDidLoad() {
    super.viewDidLoad()
    

    let myUrl = URL(string: "https://gipaa.nl/app/test.php");
    
    var request = URLRequest(url:myUrl!)
    
    request.httpMethod = "POST"// Compose a query string
    
    let accessToken: String? = KeychainWrapper.standard.string(forKey: "token")
    let userId: String? = KeychainWrapper.standard.string(forKey: "id")
    
    
    let postString = "userId=\(userId!)&token=\(accessToken!)";
    
    request.httpBody = postString.data(using: String.Encoding.utf8);
    
    let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
        
        if error != nil
        {
            print("error=\(error)")
            return
        }
        
        // You can print out response object
        // print("response = \(response)")
        //Let's convert response sent from a server side script to a NSDictionary object:
        do {
            
            
            
            
            let decoder = JSONDecoder()
            let response = try decoder.decode(Todolist.self, from: data!)
         
            let size = response.todo.count
          
            
            for (index, test) in response.todo.enumerated() {
                

                self.show.append(test.title as AnyObject)          
            }
           print(self.show.count)
            
            print(self.show)
            
        } catch {
            print(error)
        }
    }
    task.resume()
    view.backgroundColor = .white
    
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellID)

    
}

// Uncomment this block of code to achieve alternating cell colors.
//    override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
//        if indexPath.row % 2 == 0 {
//            let altCellColor: UIColor? = UIColor(white: 0.7, alpha: 0.5)
//            cell.backgroundColor = altCellColor
//        }
//    }
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.show.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cell: UITableViewCell? = tableView.dequeueReusableCell(withIdentifier: cellID)
    
    cell = UITableViewCell(style: .subtitle, reuseIdentifier: cellID)
    cell?.selectionStyle = .none
    

    cell?.textLabel?.text = show[indexPath.row] as! String

    
    

    
    return cell!
}

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    
    if editingStyle == .delete {
        self.show.remove(at: indexPath.row)
        self.tableView.deleteRows(at: [indexPath], with: .fade)
    }
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    //        let newVC = NewViewController()
    //        navigationController?.pushViewController(newVC, animated: true)
    
    let cell = tableView.cellForRow(at: indexPath)
    
    print(cell?.detailTextLabel?.text ?? "")
    
}

}

When i do

print(self.show.count)

print(self.show)

Printed Response:

6
[Loftdeur, test, test, test, test, test]

when i change to a static array i get my cells outputted.

return list.count
cell?.textLabel?.text = list[indexPath.row] as! String

What am i doing wrong here? Any help would be appriciated

When task.resume() executes, the data task is started on a background thread asynchronously, and the rest of the view controller code continues to execute on the main thread. Your table view is most likely getting loaded before the data task completes. If you put a tableView.reloadData() after the print(self.show) in your data task completion handler, the table view should load your cells correctly.

1 Like

Cool that with

       DispatchQueue.main.async
                {
                    self.myTableView.reloadData()
                    
            }

fixed the issue for me. Thanks!