1

I tried looking this up but could not find a way to stop the execution of a firebase query of type observe. Observe takes a call back and keeps running it every time the database is updated at a reference. But I want to stop this callback from running when the view disappears and again start running the query when view will appear.

So this is what I want to do. Unfortunately the observe functions returns an int and not any handler that can be used to stop the query's excution.

func viewWillDissappear(animated: Bool) {
  ...
  stopQuery()
}

func viewWillAppear(animated: Bool) {
  ...
  startQuery()
} 

func startQuery() {
  Database.database().reference().observe(.value) { (snapshot) in
   //Rest of callback to be executed only when view will appear and is visible
  }
}

func stopQuery() {
   //Stop query callback execution started by startQuery
}

Note: I don't want answers that rely on using a vairble to check if view is visible and skip the callback execution. I want to compeletly cancel the currently running query and restart it the next time view will appear.

Parth
  • 2,682
  • 1
  • 20
  • 39

3 Answers3

2

You can remove all observers:

Database.database().reference().child("ChildName").child("any sub child if any").removeAllObservers()

This will remove all the observers from this path. (Change code as per your db path and remove observer)

Please comment if you have any questions.

Happy to help!

Mohit Kumar
  • 2,898
  • 3
  • 21
  • 34
2

You may have overlooked or misread the documentation. Observers, also known as a Listener (can) return a handle and that can be used to remove an observer. The handle is in fact, an Int.

It's in the documentation under Detach Listener. When the view is closing, just use the handle to detach the listener and you're set.

There's actually an example of how to add a handle in the documentation as well - the code looks like this

refHandle = postRef.observe(DataEventType.value, with: { (snapshot) in
  let postDict = snapshot.value as? [String : AnyObject] ?? [:]
  // ...
})

You can then use removeObserverWithHandle to remove the refHandle

postRef.removeObserver(withHandle: refHandle)

Oh, I noticed this code in your question

Database.database().reference().observe(.value)

That's probably not going to be a good idea as it's adding an observer to everything in your entire database and any change to any child node will fire that event and reload everything! You're better off targeting a specific node for changes

let postsRef = Database.database().reference().child("posts")
self.postHandle = postRef.observe(....

which would only return changes within the postsRef

Jay
  • 34,438
  • 18
  • 52
  • 81
  • I know, I am using a targetted ref. This was just to give an example. But thanks for the answer. – Parth Feb 23 '21 at 04:15
  • @ParthTamane You had asked *How to stop the execution of a firebase query* and this answer shows how to do that. So.... is your question answered? If not, can you refine the question a bit so we know what part is not answered? – Jay Feb 23 '21 at 17:57
  • I think I did a mistake and now every change resolves in observing. How can I delete every observer I created? – submariner Nov 25 '22 at 14:11
  • @submariner Depending on the observer, every change is supposed to generate an event. So if you're using .childRemoved, every time a child is removed your app will receive an event. Likewise, if you're using .value then every change of any kind will present an event. You can always remove all observers which in the documentation. It's really hard to say though, based on the limited info in your comment. Perhaps posting a question with code and a description of the problem would in order? – Jay Nov 25 '22 at 15:02
  • Thanks for your answer @jay you can find my question here https://stackoverflow.com/questions/74573935/removing-the-firebase-observer-does-not-work – submariner Nov 25 '22 at 16:23
1

Unfortunately the observe functions returns an int and not any handler that can be used to stop the query's execution.

The handle FIRDatabaseHandle aka DatabaseHandle in Swift is defined as:

typedef NSUInteger FIRDatabaseHandle NS_SWIFT_NAME(DatabaseHandle);

Therefore, you're actually correct about this being an integer. But it's best if you store the returned handle to a strong variable handle, so that you can stop/remove the observer from your stopQuery() function.

Like so:

// MARK: - Properties

private var handle: DatabaseHandle?

// MARK: - Functions
...
...

func startQuery() {
  handle = Database.database().reference().observe(.value) { (snapshot) in
   //Rest of callback to be executed only when view will appear and is visible
  }
}

func stopQuery() {
   //Stop query callback execution started by startQuery.
        Database.database().reference()
            .removeObserver(withHandle: handle)
}

Remember that you need to track your whole path (ie specific child)., otherwise you might fail in removing your observer.

Glenn Posadas
  • 12,555
  • 6
  • 54
  • 95