I want to detach a snapshotListener
in a viewController when a button is pressed. I was reading other stack over flow questions and the documentation and they were calling the remove method for the listener in the same function. I tried to do that in my situation but my snapshotListener just didn't end up working at all.
Here's my function and block of code that I want to tweak.
@objc func doneTapped() {
let updateListener = db.collection("school_users/\(user?.uid)/events").whereField("event_name", isEqualTo: navigationItem.title).addSnapshotListener(includeMetadataChanges: true) { (querySnapshot, error) in
if let error = error {
print("There was an error fetching the documents: \(error)")
} else {
self.eventName = querySnapshot!.documents.map { document in
return EventName(eventName: (document.get("event_name") as! String))
}
self.db.document("school_users/\(self.user?.uid)/events/\(self.docIDUneditableTextF.text!)").updateData(["event_date": self.dateEditableTextF.text, "event_cost": self.costEditableTextF.text, "for_grades": self.gradesEditableTextF.text]) { (error) in
if let error = error {
print("There was an error updating the document: \(error)")
} else {
print("The document was successfully updated."
}
}
}
}
dateEditableTextF.resignFirstResponder()
dateEditableTextF.isEnabled = false
costEditableTextF.resignFirstResponder()
costEditableTextF.isEnabled = false
gradesEditableTextF.resignFirstResponder()
gradesEditableTextF.isEnabled = false
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(editTapped))
}
I tried calling updateListener.remove()
but it made my snapshotListener not work at all, also when the document updates, the print statement is never ending, is that also because the listener is still active or is that a different issue?
addSnapshotListener
will give you updates whenever the data changes. I'm unclear why you would want to immediately remove the listener, if you really did want to receive updates -- and, as you pointed out, immediately removing it will basically cause to it not function at all. Perhaps post a link to some of those posts/documentation where you saw the code you're referencing and someone can give insight into what's happening.
My suspicion is that you don't actually need the updates to the data. In that case, you can just use .getDocuments()
instead. See the Firestore documentation here about different ways to get data: https://firebase.google.com/docs/firestore/query-data/get-data
The second problem (the infinite print) is related to the first. Because you have a listener, which will return updates when the data changes, when you do your second database call (your updateData
), that updates your data, triggering the listener again. This will keep looping because they will keep calling each other. This is another sign that perhaps you don't actually want a listener, but a single call to get the data. If you do in fact want updates, you'll have to find a way to decouple your second request so that you don't get in the loop.
Update based on comments: (Example of removing the listener in a different function)
On your view, view controller, etc, declare a property for the listener:
class MyViewController : UIViewController {
private var documentListener: ListenerRegistration? //assuming that ListenerRegistration is the correct type here, but you can check the current type of your updateListener to check
}
Then, in your function, set your listener to that:
documentListener = db.collection("school_users/\(user?.uid)/events").whereField("event_name", isEqualTo: navigationItem.title).addSnapshotListener()...
Then, later (like in viewDidDisappear
), you can remove it:
documentListener?.remove()