Search code examples
iosjsonswift4xcode9decoding

swift 4 xcode app not reading in json file


So I have a paging app with 3 pages and each page has a details view. All three pages (views) access separate json data files. Everything worked fine until I set up the third page view and its detail view. Now the app can't seem to access the json file for the second view. It gets the path to the file and generates a local URL for the file, but either doesn't find the file or doesn't get the data out of it. Below is the code:

func downloadJSON(completed: @escaping () -> ()) {
    let path = Bundle.main.path(forResource: "Speedways", ofType: "json")
    let url = URL(fileURLWithPath: path!)

    URLSession.shared.dataTask(with: url) { data, response, error in
        guard let data = data, error == nil, response != nil else {
            return
        }
        do {
            let decoder = JSONDecoder()
            allspeedways = try decoder.decode([Speedways].self, from: data)
            var s = 0
            for speedway in allspeedways {
                self.TableData.append(speedway[s].speedway.capitalized)
                s += 1
            }
        } catch {
            print(error)
        }
    }.resume()
    DispatchQueue.main.async {
        completed()
    }
}

This is the data model:

typealias Speedways = [Speedway]

struct Speedway: Codable {
    let speedway, location, sizeOfTrack: String
    let trackEvents, trackevents: [Trackevent]?

    enum CodingKeys: String, CodingKey {
        case speedway = "Speedway"
        case location = "Location"
        case sizeOfTrack = "SizeOfTrack"
        case trackEvents = "TrackEvents"
        case trackevents
    }
}

struct Trackevent: Codable {
    let trackevent, date, pole, winner: String
    let playoff: String
}

And this is the json data (why this displays weird I don't know):

[{"Speedway":"Daytona International Speedway",
"Location":"Daytona, Fla",
"SizeOfTrack":"2.5 miles",
"TrackEvents" :[{
        "trackevent" : "Advance Auto Parts CLASH AT DAYTONA",
        "date" : "Sun, Feb 11",
        "pole" : "Austin Dillon",
        "winner" : "Brad Keselowski",
        "playoff" : "No"
        },
        .
        .
        .
        {
          .
          .
          .
        }]
 },
 {
 "Speedway":"Atlanta Motor Speedway",
 "Location":"Hampton, Ga",
 "SizeOfTrack":"1.54 miles",
 "trackevents" :[{
        "trackevent" : "Folds of Honor QuikTrip 500",
        "date" : "Sun, Feb 25",
        "pole" : "Kyle Busch",
        "winner" : "Kevin Harvick",
        "playoff" : "No"
        }]
 },

The error shows up here during execution with the message: "Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value"

    speedwaysTableView.delegate = self
    speedwaysTableView.dataSource = self

Anybody have any ideas?


Solution

  • Why for heaven's sake are you loading data in the bundle with URLSession? A local file can be read without an internet connection 😉

    Delete the typealias and get the data with

    func downloadJSON() { // the name of the function is pretty misleading
        let url = Bundle.main.url(forResource: "Speedways", withExtension: "json")!
        let data = try! Data(contentsOf: url)
        allspeedways = try! JSONDecoder().decode([Speedway].self, from: data)
        TableData = allspeedways.map{ $0.speedway.capitalized }
        // here reload the table view
    }
    

    If the code crashes you made a design mistake.

    And if speedwaysTableView.delegate = self crashes the outlet is not connected in Interface Builder