My goal is to display some data from a JSON file in a List in SwiftUI. This is for iOS 17. I have tried a lot of different things and have done some research, but cannot find the solution.
Here's an example of the JSON data:
{
“key1” : 123,
“key2” : “word”,
“key3” : [
{
“combination” : 193804,
“color” : “blue”,
“size” : 2
},
{
“combination” : 785435,
“color” : “red”,
“size” : 6
},
{
“combination” : 503953,
“color” : “yellow”,
“size” : 6
} ],
“key4” : “something”
“key5” : {
“key4a” : 54
“key4b” : “thisword”
“key4c” : “letters”
}
}
Here are my data models:
struct ThisData: Decodable {
let key1: Int
let key2: String
let key3: [OtherData]
let key4: String
let key5: ThatData
struct OtherData: Decodable {
let combination: Int
let color: String
let size: Int
}
struct ThatData: Decodable {
let key4a: Int
let key4b: String
let key4c: String
}
}
Here's the view where I'm trying to display the list. What I want to do is display, in three rows, the values for the keys "combination," "color," and "size" that are included in the array under "key3".
import SwiftUI
struct ThisView: View {
@State private var thisData: [ThisData.OtherData] = []
var body: some View {
ScrollView {
List(thisData) { info in
HStack {
Text("\(code to display variable from OtherData struct)")
}
}
}
}
}
At this point, I get the following error for the view:
Initializer 'init(_:rowContent:)' requires that 'CurrentConditions.CurrentData' conform to 'Identifiable'
I understand why -- there needs to be a unique identifier for the data nested under "key3." I did find a suggested solution, but it only works for a key in the "ThisData" struct/data model.
extension CurrentConditions: Identifiable {
var id: Int { return XXX }
}
Nothing I replace XXX with works. I feel like I'm close, but I just don't have the background knowledge to figure it out. I've spent about four hours on this.
First of all, your models should match the json data. The simple way to do that is to copy and paste your json into https://app.quicktype.io/ it will generate most of the code for you.
To rename or omit certain properties from decoding, use CodingKeys
, for example:
struct ThisData: Identifiable, Decodable {
let id = UUID() // <--- here
let key1: Int
let key2: String
//...
enum CodingKeys: String, CodingKey { // <--- here, no id present, so will not be decoded
case key1
case key2 = "created_at" // <--- here, the json data field to decode
// ....
}
struct OtherData: Identifiable, Decodable {
let id = UUID() // <--- here
let combination: Int
let color: String
let size: Int
enum CodingKeys: String, CodingKey { // <--- here, no id present, so will not be decoded
case combination, color, size
}
}
Similarly for your other models. This is a common approach to make your struct Identifiable
and not decode the id.
It is very useful to have your models with a unique id, especially those in arrays, like your OtherData
To display the list in three rows with the data "combination," "color," and "size", use something like this:
List(thisData) { info in
VStack {
Text("\(info.combination)")
Text(info.color)
Text("\(info.size)")
}
}
Note, no need for ScrollView
if you have a List
.