Hi team, I am trying to build an app for my friends business and I have hit a stumbling block where I can’t seem to capture an element of the local JSON data when using the ForEach loop. Would somebody be able to take a look at where I’m going wrong please? Should I add my code through this forum or provide a GitHub link?
Thanks, Adam
Hi Adam,
Welcome to the code crew community.
You can either post the code to say, DropBox or Google Drive and then post a share link in a reply or if you prefer, push it to GitHub (making sure that it is a public repo) and then advise the link.
Before you do that, just check that your JSON code matches your Model (struct or class) to ensure that it is being decoded successfully.
Hi Chris, thanks.
GitHub link is https://github.com/Adam-Woods-xCode/CourtierV2.git
I’m new to coding so I’m sure it’s an obvious error.
When I delete the ForEach and amend the Text to “EnterName”, it displays a single row as planned.
Thanks again
Where is this occurring in your project? You’ve posted the entire project but didn’t narrow down where the issue is.
Hi,
It’s in the SingerView.
Thanks
Three issues:
-
Your JSON has an extraneous outer array and so it doesn’t correspond to the data structure you are using for
Decodable
. Remove the[ ]
surrounding your JSON. -
The keys for your three objects in your JSON (
Singers
,Bands
,Instrumentalists
) don’t correspond to the keys in yourDecodable
data structure (singers
,bands
,instrumentalists
). You either need to adjust the capitalization so they match or use aCodingKeys
enum to supply correspondences.
Like this:
class Courtier: Identifiable, Decodable {
var id: UUID?
var singers: [Singers]
var bands: [Bands]
var instrumentalists: [Instrumentalists]
enum CodingKeys: String, CodingKey {
case id
case singers = "Singers"
case bands = "Bands"
case instrumentalists = "Instrumentalists"
}
}
- In
SingerService.getLocalData()
you are trying to decode an array ofSinger
objects:
do {
let singerData = try decoder.decode([Singers].self, from: data)
for s in singerData {
s.id = UUID()
}
return singerData
}
but the JSON you supply is actually a Courtier
type that contains an array of Singers
. So you need to change that code to:
do {
let courtier = try decoder.decode(Courtier.self, from: data)
for s in courtier.singers {
s.id = UUID()
}
return courtier.singers
}
And a suggestion:
Rename your data structures. You have Singers
, Bands
and Instrumentalists
but each of those represents one item. So they should be Singer
, Band
and Instrumentalist
.
That makes your Courtier
class read nicer:
class Courtier: Identifiable, Decodable {
var id: UUID?
var singers: [Singer]
var bands: [Band]
var instrumentalists: [Instrumentalist]
}
So singers
is an array of multiple Singer
objects, not an array of multiple Singers
objects, etc.
Thank you so much, really appreciate this.