我有一个聊天模型:
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
?
答案 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