Search code examples
jsonswiftswiftuicodable

SWIFT UI request


Im trying to make a request on Swift UI in a data file, but nothing is happening on and I seem to not be getting back any data. Im not sure where the issue is, keep in mind I just started swiftUI 2days ago. Any help would be greatly appreciated.

Data Im trying to retrieve.

[
    {
        "id": 1119,
        "make": "Audi",
        "model": "100",
        "generation": "100 Avant (4A,C4)",
        "engine_modification": "2.8 V6 E (174 Hp) quattro Automatic",
        "year": 1991,
        "powertrain_architecture": "Internal Combustion engine",
        "body_type": "Station wagon (estate)",
        "number_of_seats": 5,
        "number_of_doors": 5,
        "urban_fuel_consumption": 13.5,
        "extra_urban_fuel_consumption": 8,
        "combined_fuel_consumption": 10,
        "fuel_type": "Petrol (Gasoline)",
        "acceleration": 9.5,
        "top_speed": 207,
        "power": 174,
        "torque": 250,
        "engine_location": "Front, Longitudinal",
        "engine_displacement": 2771,
        "number_of_cylinders": 6,
        "position_of_cylinders": "V-engine",
        "number_of_valves_per_cylinder": 2,
        "fuel_system": "Multi-point indirect injection",
        "engine_aspiration": "Naturally aspirated engine",
        "kerb_weight": 1550,
        "fuel_tank_capacity": 80,
        "drive_wheel": "All wheel drive (4x4)",
        "number_of_gears": 4,
        "front_brakes": "Ventilated discs",
        "rear_brakes": "Disc"
    },
    {
        "id": 1120,
        "make": "Audi",
        "model": "100",
        "generation": "100 Avant (4A,C4)",
        "engine_modification": "2.8 V6 E (174 Hp) quattro",
        "year": 1991,
        "powertrain_architecture": "Internal Combustion engine",
        "body_type": "Station wagon (estate)",
        "number_of_seats": 5,
        "number_of_doors": 5,
        "urban_fuel_consumption": 13.5,
        "extra_urban_fuel_consumption": 8,
        "combined_fuel_consumption": 10,
        "fuel_type": "Petrol (Gasoline)",
        "acceleration": null,
        "top_speed": null,
        "power": 174,
        "torque": 250,
        "engine_location": "Front, Longitudinal",
        "engine_displacement": 2771,
        "number_of_cylinders": 6,
        "position_of_cylinders": "V-engine",
        "number_of_valves_per_cylinder": 2,
        "fuel_system": "Multi-point indirect injection",
        "engine_aspiration": "Naturally aspirated engine",
        "kerb_weight": 1550,
        "fuel_tank_capacity": 80,
        "drive_wheel": "All wheel drive (4x4)",
        "number_of_gears": 5,
        "front_brakes": "Ventilated discs",
        "rear_brakes": "Disc"
    },

Code for request

import SwiftUI
import Foundation

struct astonMartin: Decodable, Identifiable{
    let id: Int
    var make: String
    var model: String
    var generation: String
    var engine_modification: String
    var year: Int
    var powertrain_architecture: String 
    var body_type: String
    var number_of_seats: Int
    var number_of_doors: Int
    var urban_fuel_consumption: Int
    var extra_urban_fuel_consumption: Int
    var combined_fuel_consumption: Int
    var fuel_type: String
    var acceleration: Int
    var top_speed: Int
    var power: Int
    var torque: Int
    var engine_location: String
    var engine_displacement: Int
    var number_of_cylinders: Int
    var position_of_cylinders: String
    var number_of_valves_per_cylinder: Int
    var fuel_system: String
    var engine_aspiration: String
    var kerb_weight: Int
    var fuel_tank_capacity: Int
    var drive_wheel: String
    var number_of_gears: Int
    var front_brakes: String
    var rear_brakes: String
}

class secondaryCall: ObservableObject {
    @Published var cars: [astonMartin] = []

    func getCars() {
        guard let url = URL(string: "URL INSERTED HERE") else { fatalError("Missing URL") }

        let urlRequest = URLRequest(url: url)

        let dataTask = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
            if let error = error {
                print("Request error: ", error)
                return
            }

            guard let response = response as? HTTPURLResponse else { return }

            if response.statusCode == 200 {
                guard let data = data else { return }
                DispatchQueue.main.async {
                    do {
                        let decodedCars = try JSONDecoder().decode([astonMartin].self, from: data)
                        self.cars = decodedCars
                    } catch let error {
                        print("Error decoding: ", error)
                    }
                }
            }
        }

        dataTask.resume()
    }
}

content view


import SwiftUI

struct ContentView: View {
    
    @State var isLinkActive = false
    @EnvironmentObject var allCars: secondaryCall
    var body: some View {
        NavigationView{
            ZStack{
                Image("car")
                    .resizable()
                    .scaledToFill()
                    .ignoresSafeArea(.all)
                    .overlay(
                        Rectangle()
                            .opacity(0.6)
                            .ignoresSafeArea(.all)
                    )
               
                    NavigationLink(destination: HomeView()) {
                        Text("Click to view all cars")
                            .foregroundColor(.white)
                    }
                    .padding()
                    .background(.orange)
                    .clipShape(Capsule()
                    )
                   
                }
            }
        }
    }
            

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .environmentObject(secondaryCall())
    }
}

Home view:

//
//  HomeView.swift
//  project
//

//

import SwiftUI

struct HomeView: View {
    @EnvironmentObject var allCars: secondaryCall
    var body: some View {
        ScrollView{
            Text("All cars for Aston Martin")
                .bold()
                .textCase(.uppercase)
                .font(.headline)
            ForEach(allCars.cars){car in
                HStack(alignment: .top){
                    Text("\(car.make)")
                        
                }
            }
        }
        .onAppear{
            allCars.getCars()
        }
    
    }
}

struct HomeView_Previews: PreviewProvider {
    static var previews: some View {
        HomeView()
            .environmentObject(secondaryCall())
    }
}

Project App

//
//  projectApp.swift
//  project
//

//

import SwiftUI
@main 
struct projectApp: App {
    var allCars = secondaryCall()
    var body: some Scene {
        WindowGroup {
            SplashView()
                .environmentObject(allCars)
        }
    }
}


Solution

  • Form your data, I see that the reason you not getting data is that because you construct some variables in struct astonMartin with wrong type compare to the JSON you given.

    Given you some example

    • In Json: "urban_fuel_consumption": 13.5, which should be Double but in struct astonMartin you set is Int
    • In Json: "acceleration": null, which should be Double? because it is nil here but in struct astonMartin you set is Double
    • In Json: "top_speed": null, which should be Int? because it is nil here but in struct astonMartin you set is Int

    And maybe more of that ...

    You should recheck each type of variables in your struct

    Code will change like follow

    struct astonMartin: Decodable, Identifiable {
        let id: Int
        var make: String
        var model: String
        var generation: String
        var engine_modification: String
        var year: Int
        var powertrain_architecture: String
        var body_type: String
        var number_of_seats: Int
        var number_of_doors: Int
        var urban_fuel_consumption: Double // was Int
        var extra_urban_fuel_consumption: Int
        var combined_fuel_consumption: Int
        var fuel_type: String
        var acceleration: Double? // was Int
        var top_speed: Int? // was Int
        var power: Int
        var torque: Int
        var engine_location: String
        var engine_displacement: Int
        var number_of_cylinders: Int
        var position_of_cylinders: String
        var number_of_valves_per_cylinder: Int
        var fuel_system: String
        var engine_aspiration: String
        var kerb_weight: Int
        var fuel_tank_capacity: Int
        var drive_wheel: String
        var number_of_gears: Int
        var front_brakes: String
        var rear_brakes: String
    }
    

    More over, when you parse json not right it prints error in debug mode because you currently catch error there. Make sure you notice that.

    Parsing error