Dracula
Dracula

Reputation: 3090

How to stop the execution of a firebase query observe(eventType:with:)

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.

Upvotes: 1

Views: 595

Answers (3)

Jay
Jay

Reputation: 35648

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

Upvotes: 2

Glenn Posadas
Glenn Posadas

Reputation: 13283

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.

Upvotes: 1

Mohit Kumar
Mohit Kumar

Reputation: 3076

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!

Upvotes: 2

Related Questions