[ad_1]
I’m having an issue with a nested struct that’s populated from a JSON endpoint. I’ve labored out the decoding and received that each one working. I’m now having an issue utilizing a nested ForEach operate in a SwiftUI View.
Right here is the JSON information that comes from my endpoint
{
"success": true,
"message": "Approved",
"personData": {
"PersonID": 31457,
"Identify": "John Johnson Doe",
"Intercourse": "m",
"Dwelling": 0,
"BirthDate": "28 Dec 1965",
"DeathDate": "22 Dec 1995",
"BirthPlace": "Detroit, Michigan, USA",
"DeathPlace": "Avon, Oakland, Michigan",
"FatherName": "Kenneth William Doe",
"MotherName": "Dorothy Anna Hunter",
"Siblings": [
{
"id": 0,
"SiblingName": "Katrina Ann Doe"
},
{
"id": 1,
"SiblingName": "Iris Marie Doe"
}
],
"Marriages": [
{
"id": 0,
"FamilyID": 10866,
"SpouseID": 31487,
"SpouseName": "Louise Bernadette Timbers",
"MarriageDate": "26 Sep 1985",
"MarriagePlace": "Clark County, Indiana, USA",
"DivorceDate": "27 Oct 1999",
"Children": [
{
"id": 100,
"ChildName": "Timoth Kenneth Doe"
}
]
},
{
"id": 1,
"FamilyID": 10867,
"SpouseID": 31461,
"SpouseName": "Wendy Mae Jackson",
"MarriageDate": "1 Might 2001",
"MarriagePlace": "Detroit, Wayne, Michigan, USA",
"DivorceDate": "-",
"Kids": [
{
"id": 100,
"ChildName": "Patricia Ann Doe"
},
{
"id": 101,
"ChildName": "Allen Kenneth Doe"
},
{
"id": 102,
"ChildName": "Stephen Patrick Doe"
}
]
}
]
}
}
I’ve some Observables together with a operate which requests the information from the API and decodes it into personData
class NetworkRouter: ObservableObject {
@Revealed var isPersonLoaded: Bool = false
@Revealed var personData: PersonData?
func getPersonData(personID: Int) {
let information = KeychainHelper.customary.learn(service: "token", account: "blahblah")!
let token = String(information: information, encoding: .utf8)!
Webservice().getPersonData(token: token, personID: personID) { (end result) in
swap end result {
case .success(let personData):
DispatchQueue.foremost.async {
self.personData = personData
self.isPersonLoaded = true
}
case .failure(let error):
DispatchQueue.foremost.async {
print(error.localizedDescription)
}
}
}
}
}
Listed here are the struct definitions to assist decode the JSON
struct PersonResponse: Codable {
let success: Bool
let message: String
let personData: PersonData
}
struct PersonData: Codable {
let personID: Int
let title, intercourse: String
let dwelling: Int
let birthDate, deathDate, birthPlace, deathPlace: String
let fatherName, motherName: String
let siblings: [Sibling]
let marriages: [Marriage]
enum CodingKeys: String, CodingKey {
case personID = "PersonID"
case title = "Identify"
case intercourse = "Intercourse"
case dwelling = "Dwelling"
case birthDate = "BirthDate"
case deathDate = "DeathDate"
case birthPlace = "BirthPlace"
case deathPlace = "DeathPlace"
case fatherName = "FatherName"
case motherName = "MotherName"
case siblings = "Siblings"
case marriages = "Marriages"
}
}
struct Marriage: Codable, Identifiable {
let id, familyID, spouseID: Int
let spouseName, marriageDate, marriagePlace, divorceDate: String
let youngsters: [Child]
enum CodingKeys: String, CodingKey {
case id
case familyID = "FamilyID"
case spouseID = "SpouseID"
case spouseName = "SpouseName"
case marriageDate = "MarriageDate"
case marriagePlace = "MarriagePlace"
case divorceDate = "DivorceDate"
case youngsters = "Kids"
}
}
struct Little one: Codable, Identifiable {
let id: Int
let childName: String
enum CodingKeys: String, CodingKey {
case id
case childName = "ChildName"
}
}
struct Sibling: Codable, Identifiable {
let id: Int
let siblingName: String
enum CodingKeys: String, CodingKey {
case id
case siblingName = "SiblingName"
}
}
I’ve tried the next strategies for looping by every marriage and displaying the kids
struct PersonProfileMarriageView: View {
@EnvironmentObject var networkRouter: NetworkRouter
var physique: some View {
VStack {
ForEach(networkRouter.personData!.marriages) { thisMarriage in
HStack(alignment: .high, spacing: 0) {
Textual content("SPOUSE")
Textual content("(thisMarriage.spouseName)")
}
if thisMarriage.marriageDate != "-" {
HStack(alignment: .high, spacing: 0) {
Textual content("MARRIAGE DATE")
Textual content("(thisMarriage.marriageDate)")
}
}
if thisMarriage.youngsters.rely > 0 {
HStack(alignment: .high, spacing:0) {
Textual content("CHILDREN")
VStack(spacing: 0) {
ForEach(thisMarriage.youngsters) { thisChild in
Textual content("(thisChild.childName)")
}
}
}
}
}
}
}
}
I’ve additionally tried this sort of ForEeach
ForEach(networkRouter.personData!.marriages, id: .id) { thisMarriage in
ForEach(thisMarriage.youngsters) { youngsters in
}
}
And this technique
ForEach(networkRouter.personData!.marriages, id: .id) { thisMarriage in
ForEach(thisMarriage.youngsters, id: .id) { thisChild in
}
}
All of these produce the dreaded “The compiler is unable to type-check this expression in cheap time; attempt breaking apart the expression into distinct sub-expressions”
I actually do not know the best way to “break this up”
The one manner I managed to get this to work was by utilizing a Checklist on this method which appears very hacky.
Checklist(networkRouter.personData!.marriages) { thisMarriage in
ForEach(thisMarriage.youngsters, id: .id) { thisChild in
}
}
I might very a lot use some assistance on this one. I been at it for days with no success. I’ve tried to make issues Identifiable. Made certain the Marriage IDs and Little one IDs had been distinctive.
I actually dislike utilizing the Checklist because it causes problems with different issues I am attempting to do.
Hopefully I’ve supplied all of the code obligatory to help. Please let me know if I missed something.
[ad_2]
