Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

With Firebase, Swift removeObserver(withHandle does not remove the observer

With removeObserver(withHandle in Swift 3, the Observer is not removed on viewDidDisappear

var query = FIRDatabaseQuery()

var postRef: FIRDatabaseReference!
var postRefHandle: FIRDatabaseHandle?

override func viewDidLoad() {
    super.viewDidLoad()

    postRef = baseRef.child("Posts")
}

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)

    if postRefHandle != nil {
        //try 1:
        //postRef.removeObserver(withHandle: postRefHandle!)

        //try 2:
        //postRef.queryOrdered(byChild: "sortTimestamp").removeObserver(withHandle: postRefHandle!)

        //try 3: 
        //query.removeObserver(withHandle: postRefHandle!)
    }
    //try 4:
    //postRef.removeAllObservers() //works
}

func getPosts()
{
    var count = 20 

    query = postRef.queryOrdered(byChild: "sortTimestamp")

    postRefHandle = query.queryLimited(toFirst: UInt(count)).observe(.childAdded //etc.
}

So I tried the three methods in viewDidDisappear, but the observer is not removed. try 3 query.removeObserver(withHandle: postRefHandle!) as by answer from Firebase, how do I return a handle so that I can call removeObserver? by frank-van-puffelen

The only one that does work is the one outlined in try 4. Any reason why I cannot remove the Observer with removeObserver(withHandle? (try 1 - 3)

Also "query.queryLimited(toFirst: UInt(count)).observe(.childAdded" does not get the latest data from Firebase. I was under the impression the observe always gets the updated data, as opposed to observeSingleEvent. Why does it not do that?

Any suggestions are much appreciated.

like image 306
Peter de Vries Avatar asked Apr 26 '17 12:04

Peter de Vries


3 Answers

If you have the following code:

var postsRef: FIRDatabaseReference!
var postRefHandle: FIRDatabaseHandle!
var query = FIRDatabaseQuery()

func addHandler() {

    self.postsRef = self.ref.child("posts")
    var count = 20
    self.query = self.postsRef.queryOrdered(byChild: "sortTimestamp")

    self.postRefHandle = self.query.queryLimited(toFirst: UInt(count)).observe(.childAdded, with: { snapshot in
        print(snapshot) 
    })
}

and at a later time you do this function

self.postsRef.removeObserver(withHandle: self.postRefHandle!)

It removes the observer. This is tested code.

To the second part of your question: querySingleEvent and observe do the same thing data wise but have different behaviors. They will both always get current data - modified by startAt, endAt, equalTo etc.

observeSingleEvent returns the data, does NOT leave an observer so you will not be notified if that data changes

observe returns the data and leaves an observer attached to the node and will notify you of future changes.

.childAdded: when any children are added to the node .childChanges: when any children change in the node .childRemoved: when a child is removed.

like image 195
Jay Avatar answered Nov 17 '22 13:11

Jay


How I'm Able to Achieve this is by removing child reference.

var recentRef: FIRDatabaseReference!

recentRef.child("\(groupId)").observe(.value, with: { (snapshot) in

                    recentRef.removeAllObservers() // not_working
                    recentRef.child("\(groupId)").removeAllObservers() //working

                    if let obj = snapshot.value as? [String: AnyObject] {
                            //... code here
                    }
                })
like image 29
Sandeep Maurya Avatar answered Nov 17 '22 14:11

Sandeep Maurya


You can achieve this without making a query also(Swift 4) - This removes the reference of the observer properly and works for me.

    private let ref = Database.database().reference().child("classTalks")
    private var refHandle: DatabaseHandle!
    
    override func viewWillAppear(_ animated: Bool) {

        super.viewWillAppear()

        refHandle = ref.observe(.value, with: { (snapshot) in 
            ...
        })

    }
    
    override func viewWillDisappear(_ animated: Bool) {
    
        super.viewWillDisappear()

        ref.removeObserver(withHandle: refHandle)
    
    }
like image 2
Aditya Ahuja Avatar answered Nov 17 '22 12:11

Aditya Ahuja