SwiftUI ForEach嵌套结构-编译器超时和失败



我遇到了一个从JSON端点填充的嵌套结构的问题。我已经完成了解码,并使所有的工作。我现在在SwiftUI视图中使用嵌套的ForEach函数时遇到问题。

以下是来自我的端点的JSON数据

{
"success": true,
"message": "Authorized",
"personData": {
"PersonID": 31457,
"Name": "John Johnson Doe",
"Sex": "m",
"Living": 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 May 2001",
"MarriagePlace": "Detroit, Wayne, Michigan, USA",
"DivorceDate": "-",
"Children": [
{
"id": 100,
"ChildName": "Patricia Ann Doe"
},
{
"id": 101,
"ChildName": "Allen Kenneth Doe"
},
{
"id": 102,
"ChildName": "Stephen Patrick Doe"
}
]
}
]
}
}

我有一些Observable和一个函数,该函数从API请求数据并将其解码为personData

class NetworkRouter: ObservableObject {
@Published var isPersonLoaded: Bool = false
@Published var personData: PersonData?
func getPersonData(personID: Int) {
let data = KeychainHelper.standard.read(service: "token", account: "blahblah")!
let token = String(data: data, encoding: .utf8)!
Webservice().getPersonData(token: token, personID: personID) { (result) in
switch result {
case .success(let personData):
DispatchQueue.main.async {
self.personData = personData
self.isPersonLoaded = true
}
case .failure(let error):
DispatchQueue.main.async {
print(error.localizedDescription)
}
}
}
}
}

以下是帮助解码JSON 的结构定义

struct PersonResponse: Codable {
let success: Bool
let message: String
let personData: PersonData
}
struct PersonData: Codable {
let personID: Int
let name, sex: String
let living: 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 name = "Name"
case sex = "Sex"
case living = "Living"
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 children: [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 children = "Children"
}
}
struct Child: 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"
}
}

我尝试了以下方法来循环浏览每个婚姻并显示孩子

struct PersonProfileMarriageView: View {
@EnvironmentObject var networkRouter: NetworkRouter
var body: some View {
VStack {
ForEach(networkRouter.personData!.marriages) { thisMarriage in
HStack(alignment: .top, spacing: 0) {
Text("SPOUSE")
Text("(thisMarriage.spouseName)")
}
if thisMarriage.marriageDate != "-" {
HStack(alignment: .top, spacing: 0) {
Text("MARRIAGE DATE")
Text("(thisMarriage.marriageDate)")
}
}
if thisMarriage.children.count > 0 {
HStack(alignment: .top, spacing:0) {
Text("CHILDREN")
VStack(spacing: 0) {
ForEach(thisMarriage.children) { thisChild in
Text("(thisChild.childName)")
}
}
}
}
}
}
}
}

我也试过这种类型的ForEeach

ForEach(networkRouter.personData!.marriages, id: .id) { thisMarriage in
ForEach(thisMarriage.children) { children in
}
}

这种方法

ForEach(networkRouter.personData!.marriages, id: .id) { thisMarriage in
ForEach(thisMarriage.children, id: .id) { thisChild in
}
}

所有这些都会产生可怕的";编译器无法在合理的时间内对此表达式进行类型检查;尝试将表达式分解成不同的子表达式";

我真的不知道如何";打破这个";

我唯一能做到这一点的方法是以这种方式使用列表,这似乎很棘手。

List(networkRouter.personData!.marriages) { thisMarriage in
ForEach(thisMarriage.children, id: .id) { thisChild in
}
}

在这件事上我需要一些帮助。我干了好几天都没有成功。我试着让事情变得可识别。确保婚姻ID和孩子ID是唯一的。我真的不喜欢使用列表,因为它会导致我试图做的其他事情变得复杂

希望我已经提供了所有必要的代码来提供帮助。如果我错过了什么,请告诉我。

根据反馈,我能够";分解";视图更多地分为子视图。谢谢你的提示。以下内容正在发挥作用。

import SwiftUI
struct PersonProfileMarriageView: View {
@EnvironmentObject var networkRouter: NetworkRouter
var body: some View {
if networkRouter.personData!.marriages.count > 0 {
VStack {
ForEach(networkRouter.personData!.marriages) { thisMarriage in
PersonProfileMarriageSpouseNameView(marriage: thisMarriage)
PersonProfileMarriageDateView(marriage: thisMarriage)
if thisMarriage.children.count > 0 {
HStack(alignment: .top, spacing:0) {
Text("CHILDREN")
VStack(spacing: 0) {
ForEach(thisMarriage.children) { children in
PersonProfileChildView(child: children)
}
}
}
}
}

}
}
}
}

最新更新