#swift #xcode #swiftui
#swift #xcode #swiftui
Вопрос:
Я использую следующий код для отображения сообщений из базы данных firestore:
struct ChatView: View {
@ObservedObject var chatModel = ChatsViewModel()
var body: some View {
VStack {
ScrollView {
ScrollViewReader {sp in
VStack{
ForEach(self.chatModel.messages, id: .self) { message in
MessageView(message: message).id(message)
}
}
.onChange(of: chatModel.messages.count) { newValue in
guard !chatModel.messages.isEmpty else {return}
withAnimation{
sp.scrollTo(self.chatModel.messages.last)
}
}
}
}
TextField("Message", text: $message)
Button(action: {
self.chatModel.addMessage(message: Message(userId: user1, text: message, time: self.chatModel.generateCurrentTimeStamp()))
message = ""
print("button messageId (messageId)")
}) {
Text("Send")
}
}
.onAppear {
chatModel.getChats(user1: user1, user2: user2)
}
}
}
Код работает, когда я не использую scrollview. Я могу запустить два симулятора, и они «разговаривают» друг с другом. Однако, когда я включаю код scrollview, я понимаю Thread 1: Fatal error: Duplicate keys of type 'Message' were found in a Dictionary.
, почему возникает эта ошибка и что я могу сделать, чтобы ее исправить?
Соответствующий код ViewModel выглядит следующим образом:
@published var messages = [Message]()
func getChats(user1: String, user2: String) {
let group = DispatchGroup()
group.enter()
self.getDocId(user1: user1, user2: user2, group: group)
group.notify(queue: DispatchQueue.main, execute: {
self.fetchChats()
})
}
func addMessage(message: Message) {
do{
let _ = try db.collection("Chats").document(self.docId).collection("messages").addDocument(from: message)
print("message sent")
} catch {
print(error)
}
}
func fetchChats() {
let ref = db.collection("Chats").document(self.docId)
ref.collection("messages").order(by: "time").addSnapshotListener { (querySnapshot, error) in
guard let documents = querySnapshot?.documents else {
print("No documents")
return
}
self.messages = documents.compactMap { (queryDocumentSnapshot) -> Message? in
return try? queryDocumentSnapshot.data(as: Message.self)
}
}
}
И вот сообщение:
struct Message: Codable, Identifiable, Hashable {
var id: String? = UUID().uuidString
@DocumentID var documentId: String?
var userId: String
var text: String
var time: String
init(documentId: String = "",
userId: String = "",
text: String = "",
time: String = "") {
self.documentId = documentId
self.userId = userId
self.text = text
self.time = time
}
enum CodingKeys: String, CodingKey {
case documentId
case userId
case text
case time
}
}
Комментарии:
1. Не могли бы вы показать свое объявление
Message
?2. Я только что отредактировал сообщение
Ответ №1:
Ваше сообщение идентифицируемо, поэтому попробуйте использовать его id
там, где это необходимо, следующим образом
VStack{
ForEach(self.chatModel.messages) { message in
MessageView(message: message).id(message.id)
}
}