SwiftUI - 将 ForEach 与不符合可识别/可散列的绑定数组一起使用
SwiftUI - using ForEach with a Binding array that does not conform to identifiable / hashable
我有一个可编码对象如下:
struct IncidentResponse: Codable {
let incident: IncidentDetails?
}
struct IncidentDetails: Codable, Identifiable {
let id: String?
let reason: IncidentReasonResponse?
let message: String?
let startedAt: String?
let endedAt: String?
}
struct IncidentReasonResponse: Codable, Identifiable {
let id: String?
let name: String?
let code: String?
let inOp: Bool?
}
这是从 API 调用时的事件响应示例:
{
"incident": {
"id": "610aebad8c719475517e9736",
"user": null,
"reason": {
"name": "No aircraft",
"code": "no-aircraft",
"inOp": true
},
"message": "test this",
"startedAt": "2021-08-04T19:34:05+0000",
"endedAt": null
}
}
在 SwiftUI 中,我试图显示这些列表。所以我有一个名为 existingIncidents 的 IncidentResponse 对象数组,然后是以下内容:
var body: some View {
List {
Section(header: Text("Existing incidents")) {
if let existingIncidents = self.existingIncidents {
ForEach(existingIncidents) { incident in
VStack(alignment: .leading) {
HStack {
Image.General.incident
.foregroundColor(Constants.iconColor)
Text(incident.incident?.reason?.name ?? "")
.foregroundColor(Constants.textColor)
.bold()
}
Spacer()
HStack {
Image.General.clock
.foregroundColor(Constants.iconColor)
Text(incident.incident?.startedAt ?? "No date")
.foregroundColor(Constants.textColor)
}
Spacer()
HStack {
Image.General.message
.foregroundColor(Constants.iconColor)
Text(incident.incident?.message ?? "No message")
.foregroundColor(Constants.textColor)
}
}
}
}
}
}
.listStyle(PlainListStyle())
但是,我无法按原样使用 existingIncidents,因为它不符合 Identifiable 或 Hashable(因此我无法使用 id: /.self 解决方法)...
我该如何解决这个问题?
我尝试像这样将 UUID 添加到 IncidentResponse 中:
struct IncidentResponse: Codable {
let incident: IncidentDetails?
var id = UUID().uuidString
}
但是,这会阻止对象从 API 正确解码。
选项 1:
给你的 IncidentResponse
一个 ID,然后告诉它不要尝试解码值:
struct IncidentResponse: Codable, Identifiable {
var id = UUID()
let incident: IncidentDetails?
enum CodingKeys: String, CodingKey {
case incident
}
}
选项 2:
使 incident
和 id
成为非可选的,然后使用它来获取 id:
ForEach(existingIncidents, id: \.incident.id) { incident in
我还会注意到 IncidentResponse
在这一点上似乎是一个毫无意义的包装。当您进行解码并将值存储到 existingIncidents
(您尚未显示)时,您可能会像 [IncidentDetails]
一样存储它们。在这种情况下,您只需要在 IncidentDetails
上使 id
属性 成为非可选的并将其声明为 Identifiable
。例如:
struct IncidentDetails: Codable, Identifiable {
let id: String
let reason: IncidentReasonResponse?
let message: String?
let startedAt: String?
let endedAt: String?
}
//....
let existingIncidentsWrappers : [IncidentResponse] = //...
let existingIncidents : [IncidentDetails] = existingIncidentsWrappers.compactMap { [=12=].incident }
我有一个可编码对象如下:
struct IncidentResponse: Codable {
let incident: IncidentDetails?
}
struct IncidentDetails: Codable, Identifiable {
let id: String?
let reason: IncidentReasonResponse?
let message: String?
let startedAt: String?
let endedAt: String?
}
struct IncidentReasonResponse: Codable, Identifiable {
let id: String?
let name: String?
let code: String?
let inOp: Bool?
}
这是从 API 调用时的事件响应示例:
{
"incident": {
"id": "610aebad8c719475517e9736",
"user": null,
"reason": {
"name": "No aircraft",
"code": "no-aircraft",
"inOp": true
},
"message": "test this",
"startedAt": "2021-08-04T19:34:05+0000",
"endedAt": null
}
}
在 SwiftUI 中,我试图显示这些列表。所以我有一个名为 existingIncidents 的 IncidentResponse 对象数组,然后是以下内容:
var body: some View {
List {
Section(header: Text("Existing incidents")) {
if let existingIncidents = self.existingIncidents {
ForEach(existingIncidents) { incident in
VStack(alignment: .leading) {
HStack {
Image.General.incident
.foregroundColor(Constants.iconColor)
Text(incident.incident?.reason?.name ?? "")
.foregroundColor(Constants.textColor)
.bold()
}
Spacer()
HStack {
Image.General.clock
.foregroundColor(Constants.iconColor)
Text(incident.incident?.startedAt ?? "No date")
.foregroundColor(Constants.textColor)
}
Spacer()
HStack {
Image.General.message
.foregroundColor(Constants.iconColor)
Text(incident.incident?.message ?? "No message")
.foregroundColor(Constants.textColor)
}
}
}
}
}
}
.listStyle(PlainListStyle())
但是,我无法按原样使用 existingIncidents,因为它不符合 Identifiable 或 Hashable(因此我无法使用 id: /.self 解决方法)...
我该如何解决这个问题?
我尝试像这样将 UUID 添加到 IncidentResponse 中:
struct IncidentResponse: Codable {
let incident: IncidentDetails?
var id = UUID().uuidString
}
但是,这会阻止对象从 API 正确解码。
选项 1:
给你的 IncidentResponse
一个 ID,然后告诉它不要尝试解码值:
struct IncidentResponse: Codable, Identifiable {
var id = UUID()
let incident: IncidentDetails?
enum CodingKeys: String, CodingKey {
case incident
}
}
选项 2:
使 incident
和 id
成为非可选的,然后使用它来获取 id:
ForEach(existingIncidents, id: \.incident.id) { incident in
我还会注意到 IncidentResponse
在这一点上似乎是一个毫无意义的包装。当您进行解码并将值存储到 existingIncidents
(您尚未显示)时,您可能会像 [IncidentDetails]
一样存储它们。在这种情况下,您只需要在 IncidentDetails
上使 id
属性 成为非可选的并将其声明为 Identifiable
。例如:
struct IncidentDetails: Codable, Identifiable {
let id: String
let reason: IncidentReasonResponse?
let message: String?
let startedAt: String?
let endedAt: String?
}
//....
let existingIncidentsWrappers : [IncidentResponse] = //...
let existingIncidents : [IncidentDetails] = existingIncidentsWrappers.compactMap { [=12=].incident }