Remove observer after value change in Firebase

12,145

This is one of the cases where you need to take an extra step in Swift, since it doesn't realize that you can safely access handle inside the block.

One way of working around this is:

let ref = Firebase(url: "https://yours.firebaseio.com/")
var handle: UInt = 0
handle = ref.observeEventType(.Value, withBlock: { snapshot in
    print(snapshot)
    if snapshot.exists() && snapshot.value as! String == "42" {
        print("The value is now 42")
        ref.removeObserverWithHandle(handle)
    }
})

By explicitly initializing the handle variable, we remove the error from the Swift compiler. But given that the handle will have been set before our block is invoked, we can safely call ref.removeObserverWithHandle(handle) inside the block.

Share:
12,145
Eugene G.
Author by

Eugene G.

iOS Engineer

Updated on June 19, 2022

Comments

  • Eugene G.
    Eugene G. about 2 years

    I have global observer in ViewController and need some different observers inside it for specific values like one below. Is it possible to remove observer after value change once?

    var ref = Firebase(url: "https://<FIREBASE-APP>.firebaseio.com/")
    
    let handle = ref.observeEventType(.Value, withBlock: { snapshot in
    
        //Here VALUE Changes to NEW_VALUE
        if snapshot.value as! String == NEW_VALUE {
    
            //IS IT POSSIBLE TO REMOVE HANDLE HERE????
            ...something here
        }
    
    })
    
    //NOT HERE
    ...ref.removeObserverWithHandle(handle)
    
  • Jay
    Jay about 8 years
    The .value is going to cause an issue as it will return all of the values with the node, which would be a dictionary structure which cannot be compared to a string. Probably a for child in snapshot.children would do it. Also, no need for a handle at all in that if we want to observe one change, just do ref.removeAllObservers inside the block. :-)
  • Frank van Puffelen
    Frank van Puffelen about 8 years
    Good point on the structure @Jay. But I disagree with calling ref.removeAllObservers(). That will (as the name says) remove all observers, which is not the same. Although it may work for this simple snippet, in general I prefer to have a symmetry between adding listeners and removing them,
  • Jay
    Jay about 8 years
    Hmm. I like the symmetry aspect. Question for clarification; If you add a .Value observer to a node, that will fire on any add, edit or remove events. If you remove the handle from the that node, you will no longer receive any of those events. Won't ref.removeAllObservers have the same effect?
  • Frank van Puffelen
    Frank van Puffelen about 8 years
    If you have a single listener on a ref, then calling ref.removeObserverWithHandle() and ref.removeAllObservers() will have the same effect. It'd be a reasonable approach if you're in cleanup-code (a destructor, close() method, etc). But if you're explicitly looking to remove a specific listener, I'd prefer removeObserverWithHandle