I am trying to create a navigationLink that pushes to some dynamic list view, unfortunately the view I'm pushing to isn't showing the corresponding data.
My data is parsed from quite complex JSON which has arrays within arrays. I'm new to coding and the only way I can figure to access the nested data is to specify a particular element within the arrays, but by doing that i essentially have created a static list view in the view I'm pushing to.
I would really appreciate a nudge in the right direction. Ive been pulling my hair out. Thanks in advance.
struct MakeList: View {
var body: some View {
HStack {
NavigationView{
List(vehicleData.makes) { i in
HStack {
NavigationLink(destination: ModelList()){
Image(i.models[0].badges[0].logoName)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 50, height: 50)
Text(i.makesName)
}
}
}.navigationTitle("Make")
}
}
}
}
struct ModelList: View {
var body: some View {
List(vehicleData.makes[0].models) { i in
Text(i.modelName)
Text(i.badges[0].series ?? "no series")
}.navigationTitle("Models")
}
}
Getting data:
func load<T: Decodable>(_ filename: String) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) in main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
var vehicleData: VehicleStruct = load("vehicleValuationData - nested version.json")
// MARK: - VehicleStruct
struct VehicleStruct: Codable, Identifiable {
var id = UUID()
let makes: [MakeStruct]
enum CodingKeys: String, CodingKey {
case makes
}
}
// MARK: - Make
struct MakeStruct: Codable, Identifiable {
var id = UUID()
let makesName: String
let models: [ModelStruct]
enum CodingKeys: String, CodingKey {
case makesName
case models
}
}
// MARK: - Model
struct ModelStruct: Codable, Identifiable {
var id = UUID()
let modelName: String
let badges: [BadgeStruct]
enum CodingKeys: String, CodingKey {
case modelName
case badges
}
}
// MARK: - Badge
struct BadgeStruct: Codable, Identifiable {
var id = UUID()
let badgeName: String
let series: String?
let year: Int
let fuel: String
let driveType: String
let bodyType: String
let transmission: String
let manualDeduction: Int
let priceWhenNew: Int
let depreciationForKms, algorithmValuation: Double
let valuerValuation: Int
let valo: Double
let logoName: String
enum CodingKeys: String, CodingKey {
case badgeName
case series
case year
case fuel
case driveType
case bodyType
case transmission
case manualDeduction
case priceWhenNew
case depreciationForKms
case algorithmValuation
case valuerValuation
case valo
case logoName
}
}
JSON example
{
"makes": [
{
"makesName": "Alfa Romeo",
"models": [
{
"modelName": "147",
"badges": [
{
"badgeName": "Twin Spark",
"series": null,
"year": 2004,
"fuel": "Petrol",
"driveType": "2WD",
"bodyType": "Small Hatch",
"transmission": "Automatic",
"manualDeduction": -250,
"subtraction1": null,
"subtraction1Difference": 0,
"add1": "Sunroof",
"add1Difference": 250,
"add2": null,
"add2Difference": 0,
"add3": null,
"add3Difference": 0,
"add4": null,
"add4Differnece": 0,
"avgAnnualKms": 15000,
"age": 16,
"averageKmsForYear": 240000,
"priceWhenNew": 0,
"depreciationForKms": 0,
"algorithmValuation": 0,
"valuerValuation": 500,
"valo": 500,
"logoName": "Alfa"
}
]
}...
Just pass the corresponding object of type MakeStruct
to your subview ModelList
:
NavigationLink(destination: ModelList(make: i)){
Image(i.models[0].badges[0].logoName)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 50, height: 50)
Text(i.makesName)
}
struct ModelList: View {
let make: MakeStruct
var body: some View {
List(self.make.models) { i in
Text(i.modelName)
Text(i.badges[0].series ?? "no series")
}.navigationTitle("Models")
}
}