带有 \.self 的 Swift ForEach 循环

时间:2021-03-14 14:19:45

标签: swift

我有一个聊天模型:

struct Chat: Encodable, Decodable {
    var messageId: String
    var textMessage: String
    var avatarUrl: String
    var photoUrl: String
    var senderId: String
    var username: String
    var date: Double
}

我使用 ForEach 像这样循环:

ForEach(chatViewModel.chatArray, id: \.messageId) { chat in
     VStack(alignment: .leading) {
         TextMessageRow(chat: chat)
     }.padding(.top,20)
}

在某些情况下,messageId 不会出现在数据库中(或为空),这会导致从 firestore 返回数据的问题

所以我尝试使用 self

ForEach(chatViewModel.chatArray, id: \.self) { chat in
         VStack(alignment: .leading) {
             TextMessageRow(chat: chat)
         }.padding(.top,20)
    }

我得到以下信息:

Generic struct 'ForEach' requires that 'Chat' conform to 'Hashable'

数据库中不存在的值在它不可用时导致错误,还有什么我可以使用的吗?让它不使用messageId

1 个答案:

答案 0 :(得分:1)

ForEach 需要一个需要可散列的 ID,因此它唯一标识视图并在关联对象发生更改时专门重新加载它,如果您的 messageID 有时可能为空,您可以尝试使用其他一些您认为独一无二的 Chat 字段可能是 textMessage

ForEach(chatViewModel.chatArray, id: \.textMessage) { chat in

因为您的 Chat 数据模型中的所有属性都已经确认了 Hashable 协议,您可以通过指定简单地使您的 Chat 模型可散列

struct Chat: Encodable, Decodable, Hashable {
    var messageId: String
    var textMessage: String
    var avatarUrl: String
    var photoUrl: String
    var senderId: String
    var username: String
    var date: Double
}

但是如果您不想让数据模型的所有属性都参与哈希值的计算,而想使用特定的属性值,您可以使用这些属性重复调用combine,如下所示

struct Chat: Encodable, Decodable, Hashable {
    var messageId: String
    var textMessage: String
    var avatarUrl: String
    var photoUrl: String
    var senderId: String
    var username: String
    var date: Double

    func hash(into hasher: inout Hasher) {
        hasher.combine(messageId)
        hasher.combine(textMessage)
        hasher.combine(senderId)
    }
}

现在您可以使用 ForEach(chatViewModel.chatArray, id: \.self) { chat in

有关 Hashable 协议的更多详细信息,您可以查看 https://www.hackingwithswift.com/example-code/language/how-to-conform-to-the-hashable-protocol

相关问题