Vedant
Vedant

Reputation: 339

Swift - JSON decoding returning empty array

For my first Swift UIKit app, I am trying to parse some JSON data and use it to populate a UITableView. Ideally, the table view would update with changes to the JSON but this is not entirely necessary right now as the JSON will change very infrequently.

But I'm having some issues parsing the JSON - I seem to be getting an empty array...

The code in my main View Controller

import Foundation
import UIKit

//TODO - JSON

struct Visualisation: Codable {
    var id: Int
    let name, info, url_name, tags: String
}

/*
JSON:

[
    {
        "id": 0,
        "name": "Two Body Collision",
        "info": "A 2D body collision under the elastic collision assumption",
        "url_name": "https://www.imperialvisualisations.com/visualisations/two-body-collision/two-body-collision/",
        "tags": "Physics, Mechanics"

    },
    {
        "id": 1,
        "name": "Waves in Dielectrics",
        "info": "The effect of incidence angle & refractive index of dielectric on reflection & transmission",
        "url_name": "https://www.imperialvisualisations.com/visualisations/2d-and-3d-coordinate-systems/2d-polar-coordinates/",
        "tags": "Physics, Maths, Matrices, Linear algebra"
    }
]

This is the structure I am aiming for:

var visualisations: [Visualisation] = [
    .init(id:0, name: "Two Body Collision", info: "A 2D body collision under the elastic collision assumption", url_name: "https://www.imperialvisualisations.com/visualisations/two-body-collision/two-body-collision/", tags: "Physics, Mechanics"),
    .init(id:2, name: "Waves in Dielectrics", info: "The effect of incidence angle & refractive index of dielectric on reflection & transmission", url_name: "https://www.imperialvisualisations.com/visualisations/single-wave-in-3d/boundry-conditions/", tags: "Physics, Electromagnetism, Light, Refractive index, Angle of incidence")
]

 */

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!


    var visualisations = [Visualisation]()

    override func viewDidLoad() {
        super.viewDidLoad()

        guard let url = URL(string: "https://api.myjson.com/bins/1ao7in") else { fatalError("JSON URL not found") }

        URLSession.shared.dataTask(with: url) { (data, _, _) in
            guard let data = data else { fatalError("JSON data not loaded") }

            guard let decodedVisualisations = try? JSONDecoder().decode([Visualisation].self, from: data) else { fatalError("Failed to decode JSON")}

            DispatchQueue.main.async{
                self.visualisations = decodedVisualisations
            }

        }.resume()

        print("visualisations")
        print(visualisations)

        tableView.delegate = self
        tableView.dataSource = self


        navigationController?.navigationBar.prefersLargeTitles = true
        title = "Visualisations"

    }

}

extension ViewController: UITableViewDataSource, UITableViewDelegate {

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

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

        //visualisation at row in view
        let visualisation = visualisations[indexPath.row]
        //recast! ??
        let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell

        cell.setCell(visualisation: visualisation)

        //set Cell just sets the elements of the table cell in another file

        return cell

    }
}


I am not getting any error messages however the decoding seems to be doing nothing to the 'visualisations' array.

Any help would be appreciated - thanks.

Upvotes: 1

Views: 972

Answers (1)

David Thorn
David Thorn

Reputation: 129

As per @vadian commented, this works just fine.

struct Visualisation: Codable {
    var id: Int
    let name, info, url_name, tags: String
}

class ViewController: UIViewController {

    var visualisations = [Visualisation]()

    override func viewDidLoad() {
        super.viewDidLoad()

        guard let url = URL(string: "https://api.myjson.com/bins/1ao7in") else { fatalError("JSON URL not found") }

        URLSession.shared.dataTask(with: url) { (data, _, _) in
            guard let data = data else { fatalError("JSON data not loaded") }

            do {
                let decodedVisualisations = try JSONDecoder().decode([Visualisation].self, from: data)
                self.visualisations = decodedVisualisations
            } catch let error {
                debugPrint(error.localizedDescription)
            }
        }.resume()

    }
}

Upvotes: 1

Related Questions