For my chat, I have a function in a class where I create a SnapshotListener on the collection "messages". For performance concern I limit the amount of documents returned to 20. What I would like to do is to change this limit and add 20 more documents for each button click and have the SnapshotListener now adjust to these 40 documents. How can I do this? It's easy when it's not in a SnapshotListener but how do I do it with it?
func readAllMessages() {
let docRef = ref.collection("discussions").document(id)
docRef.collection("messages")
.order(by: "dateCreated", descending: true)
.limit(to: 20)
.addSnapshotListener { (snap, err) in
guard let documents = snap?.documents.reversed() else {
print(err!.localizedDescription)
return
}
self.messages = documents.compactMap { (QueryDocumentSnapshot) -> Message_M? in
return try? QueryDocumentSnapshot.data(as: Message_M.self)
}
}
}
CodePudding user response:
Queries in Firestore are immutable, so there's no way to change a query that you've already attached a listener to. You'll have to create a new query with the new limit(to: 40)
and then attach a new listener to that.
If you have disk persistence enabled (which it is by default), the first 20 documents will come from the local cache, so you should only get charged document reads for the 20 new documents.
CodePudding user response:
I have almost solved my problem. With this code it works but as soon as I write a new message (document) the quantity returned by the request goes back to its origin (for my tests, limitToRead = 2). So if i only click on the button it's working (i got 2,4,6,8, etc. messages on the chat with the right order) but as soon as i send a message to an other user or receive a message (a new write on the messages collection) it goes back to 2 messages.
My modified function :
func readAllMessages(limitToRead: Int) {
let docRef = ref.collection("discussions").document(id)
docRef.collection("messages")
.order(by: "dateCreated", descending: true)
.limit(to: limitToRead)
.addSnapshotListener { (snap, err) in
guard let documents = snap?.documents.reversed() else {
print(err!.localizedDescription)
return
}
self.messages = documents.compactMap { (QueryDocumentSnapshot) -> Message_M? in
return try? QueryDocumentSnapshot.data(as: Message_M.self)
}
}
}
MyView :
...
@State private var limitToRead: Int = 2
init(...) {
...
messageData.readAllMessages(limitToRead: 2)
...
}
...
Button {
limitToRead = 2
messageData.readAllMessages(limitToRead: limitToRead)
} label: {
Text("Tap me!")
.padding()
.foregroundColor(.white)
.background(.red)
}
...
As Frank suggests, how do I create a new query and new listener in this function and attach my message array to it?
Update :
I also tried this = same result :
func readAllMessages(limitToRead: Int, newListener: Bool) {
let docRef = ref.collection("discussions").document(id)
var listener = docRef.collection("messages")
.order(by: "dateCreated", descending: true)
.limit(to: limitToRead)
.addSnapshotListener { (snap, err) in
guard let documents = snap?.documents.reversed() else {
print(err!.localizedDescription)
return
}
self.messages = documents.compactMap { (QueryDocumentSnapshot) -> Message_M? in
return try? QueryDocumentSnapshot.data(as: Message_M.self)
}
}
if newListener == true {
listener.remove()
listener = docRef.collection("messages")
.order(by: "dateCreated", descending: true)
.limit(to: limitToRead)
.addSnapshotListener { (snap, err) in
guard let documents = snap?.documents.reversed() else {
print(err!.localizedDescription)
return
}
self.messages = documents.compactMap { (QueryDocumentSnapshot) -> Message_M? in
return try? QueryDocumentSnapshot.data(as: Message_M.self)
}
}
}
}