BLACK FRIDAY SALE: Save big on all my Swift books and bundles! >>

Need help, simulator not working...

Forums > Swift

Hi all. I have an error as Xcode isn’t letting me parse my JSON file data into an array. It says in the diagnostic report that “Fatal error: Fatal error: Couldn't parse Rest.json as Array<Restaurants>: The data couldn’t be read because it isn’t in the correct format.: So if anyone could help, I would appreciate it! I am trying to follow this tutorial, and the simulator is not working in the xcode file: RestaurantRows.swift

  • Harri

Tutorial:https://www.youtube.com/watch?v=Xetrbmnszjc&t=901s Github: https://github.com/HSSwift/SwiftCode

1      

Did you not ask the same question Xcode 12.2, App and simulator crashing during parsing JSON file into array

Your JSON files is still incorrect you are missing { before the first line and } at after the last line, however I would take out the "restaurants": all together

then make a new Swift file with this in (I called Resaurant)

import Foundation

struct Restaurant: Decodable, Identifiable {
    let id: Int
    let name: String
    let imageName: String
    let description: String
    let category: String
}

make another new Swift file with in (called Bundle-Decodable)

import Foundation

extension Bundle {
    func decode<T: Decodable>(_ type: T.Type, from file: String, dateDecodingStrategy: JSONDecoder.DateDecodingStrategy = .deferredToDate, keyDecodingStrategy: JSONDecoder.KeyDecodingStrategy = .useDefaultKeys) -> T {
        guard let url = self.url(forResource: file, withExtension: nil) else {
            fatalError("Failed to locate \(file) in bundle.")
        }

        guard let data = try? Data(contentsOf: url) else {
            fatalError("Failed to load \(file) from bundle.")
        }

        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = dateDecodingStrategy
        decoder.keyDecodingStrategy = keyDecodingStrategy

        do {
            return try decoder.decode(T.self, from: data)
        } catch DecodingError.keyNotFound(let key, let context) {
            fatalError("Failed to decode \(file) from bundle due to missing key '\(key.stringValue)' not found – \(context.debugDescription)")
        } catch DecodingError.typeMismatch(_, let context) {
            fatalError("Failed to decode \(file) from bundle due to type mismatch – \(context.debugDescription)")
        } catch DecodingError.valueNotFound(let type, let context) {
            fatalError("Failed to decode \(file) from bundle due to missing \(type) value – \(context.debugDescription)")
        } catch DecodingError.dataCorrupted(_) {
            fatalError("Failed to decode \(file) from bundle because it appears to be invalid JSON")
        } catch {
            fatalError("Failed to decode \(file) from bundle: \(error.localizedDescription)")
        }
    }
}

PS read Paul's on how this is made How to decode JSON from your app bundle the easy way

then make a new SwiftUI View (called RestaurantRowView) with this in

import SwiftUI

struct RestaurantRowView: View {
    let restaurant: Restaurant

    var body: some View {
        HStack {
            Image(restaurant.imageName)
                .resizable()
                .scaledToFit()
                .frame(width: 50, height: 50)
                .cornerRadius(10)
                .shadow(radius: 10)

            VStack(alignment: .leading) {
                Text(restaurant.name)
                    .font(.headline)
                    .bold()

                Text(restaurant.description)
                    .foregroundColor(.secondary)
                    .multilineTextAlignment(.leading)
            }
        }
    }
}

struct RestaurantRowView_Previews: PreviewProvider {
    static let restaurants = Bundle.main.decode([Restaurant].self, from: "Rest.json")

    static var previews: some View {
        RestaurantRowView(restaurant: restaurants[0])
            .previewLayout(.sizeThatFits)
    }
}

ps please note the position of static let restaurants not in the static var previews

then in your RestaurantsView or ContentView put this in

import SwiftUI

struct RestaurantsView: View { // if using ContentView then use that here instead of RestaurantView
    let restaurants = Bundle.main.decode([Restaurant].self, from: "Rest.json")

    var body: some View {
        List(restaurants) { restaurant in
           RestaurantRowView(restaurant: restaurant)
        }
    }
}

struct RestaurantsView_Previews: PreviewProvider {
    static var previews: some View {
        RestaurantsView()
    }
}

If you want to look at the Project that tested this with here on GitHub https://github.com/NigelGee/RestaurantsApp

Happy coding

1      

Hacking with Swift is sponsored by RevenueCat

SPONSORED In-app subscriptions are a pain to implement, hard to test, and full of edge cases. RevenueCat makes it straightforward and reliable so you can get back to building your app. Oh, and it's free if your app makes less than $10k/mo.

Learn more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.