SwiftUI - 将 ForEach 与不符合可识别/可散列的绑定数组一起使用
Posted
技术标签:
【中文标题】SwiftUI - 将 ForEach 与不符合可识别/可散列的绑定数组一起使用【英文标题】:SwiftUI - using ForEach with a Binding array that does not conform to identifiable / hashable 【发布时间】:2021-09-28 20:52:15 【问题描述】:我有一个可编码的对象如下:
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())
但是,我无法使用现有事件,因为它不符合 Identifiable 或 Hashable(因此我无法使用 id: /.self 解决方法)...
我该如何解决这个问题?
我尝试将 UUID 添加到 IncidentResponse 中,如下所示:
struct IncidentResponse: Codable
let incident: IncidentDetails?
var id = UUID().uuidString
但是,这会阻止对象从 API 正确解码。
【问题讨论】:
您确定IncidentDetails
有一个可选 id
属性,还是一直存在?
我可能可以将其设为非可选
好的——同样,IncidentDetails?
在顶层真的是可选的吗?
再一次,不 - 为了公平起见,我已经在可选选项上进行了 OTT
@DevB1 你需要它来解码,但你可以稍后放弃它(见我回答的最后一部分)
【参考方案1】:
选项 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 $0.incident
【讨论】:
非常感谢 - 我已经实现了第一个选项,并且效果很好。再次感谢:) 当然。如果有帮助,请考虑点赞。以上是关于SwiftUI - 将 ForEach 与不符合可识别/可散列的绑定数组一起使用的主要内容,如果未能解决你的问题,请参考以下文章
显示来自 Observable Object SwiftUI 的列表