What Does the Snapshot/Observer Code Do in Firebase

What does a Firebase observer actually do?

The Firebase client keeps an open socket connection to its backend server. When you attach the observer, it sends that information to the server, which will from then on track the observed location. The server also sends back the current value (or lack thereof) on the location. The client will immediately fire/invoke your completion block with that value.

After this initial flow, whenever the value at the location changes, the Firebase server sends an update to the client over the open socket. When the client receives such an update, it invokes the completion block again with the updated value (or lack thereof).

Firebase Observer Event Type

The .child* events fire on child nodes of the location/query that you observe, while .value fires on the location/query itself. This means that the value you get is one level higher up in the JSON, and you'll need to loop over the results:

mostRecent.observe(.value) { (snapshot: DataSnapshot) in
for child in snapshot.children.allObjects as! [DataSnapshot] {
let (post, error) = PostFetcher.parsePostSnapshot(snapshot: child)
if let post = post {
self.latestPosts.append(post)
if let postId = post.postId { print("PostId = \(postId)") }
}
if let error = error {
print("\(#function) - \(error)")
}
}
}

Alternatively, you can listen to the .childChanged and .childRemoved events (in addition to .childAdded that you already have) and handle them separately. This may be better in cases where you need to update the UI efficiently, since it allows you to handle each individual case (new node, changed, node, removed node) in the most efficient way.

Swift 4, Firebase how to observe the snapshot and convert into object

Use the below code to get your required values

    guard let uid = Auth.auth().currentUser?.uid else {
return
}

let ref = Database.database().reference().child("users").child("\(uid)")
ref.child("Dream").observe(.value, with: { (snapshot) in
guard let dictionary = snapshot.value as? [String : AnyObject] else {
return
}
print(dictionary["content"] as? String)

}, withCancel: nil)

ref.child("Grocerylist").observe(.value, with: { (snapshot) in
guard let dictionary = snapshot.value as? [String : AnyObject] else {
return
}
print(dictionary["content"] as? String)

}, withCancel: nil)

Completion handler Firebase observer in Swift

The code you're using declares stadiums outside of the observer. This means any time a change is made to the value of the database reference, you're appending the data onto stadiums without clearing what was there before. Make sure to remove the data from stadiums before appending the snapshots again:

func getStadiums(complition: @escaping ([Stadium]) -> Void){
var stadiums: [Stadium] = []
let stadiumRef = Database.database().reference().child("Stadium")
stadiumRef.observe(.value, with: { (snapshot) in
stadiums.removeAll() // start with an empty array
for snap in snapshot.children {
guard let stadiumSnap = snap as? DataSnapshot else {
print("Something wrong with Firebase DataSnapshot")
complition(stadiums)
return
}
let stadium = Stadium(snap: stadiumSnap)
stadiums.append(stadium)
}
complition(stadiums)
})
}

Why does Firebase observeEventType return a snapshot everytime in viewWillAppear?

One answer is to simply let the observer do it's job and update your data in the background.

So if the user is on controllerA the observer updates a datasource (an array) so then the UI is updated from that array.

When the user switches to controllerB, the observer can still update the array, but don't update the UI in controllerA since there's no need to.

When the user switches back to A you'll have current data available so just reload the tableView (assuming iOS here) from the array.

This solution reduces the 'polling' nature and let's Firebase do the heavy lifting to notify your app when it needs to. You're just reloading the tableViews from an array when that controller becomes active.

Edit

The idea here is to add the observer once - perhaps when the view loads the first time only (viewDidLoad) or maybe in your app delegate. Once you add the observer it will update your dataSource arrays when data changes so when you move from view to view the only action needed will be to reload the tableView from the updated array.

There are times when you may want to remove an observer but it doesn't sound like you need to do that from your question. So - attach the observers once and let them update the dataSource arrays as the data changes. Reload your tableViews when switching views.

How do you convert a firebase snapshot of observeDataEventType.value to observeSingleEvent?

This function

someRef.observeSingleEvent(of: .value, with: { snapshot in

reads the node someRef and returns its child data as a snapshot one time and one time only, not leaving an observer. Further changes will not fire an event (the code in the closure)

This

someRef.observe(.value, with: { snapshot in

Adds an observer to the someRef node, retrieving its child data and leaving an observer on that node. Any future changes of any kind will cause an event and the code in the closure is passed a snapshot containing all of the child data.

Note that both functions are expecting a DataEventType so you can just shorten it to .value, .childAdded etc.

So in essence you don't need to 'convert' one to the other as they have different functions but return the same data - at least initially. .observe will continue to feed data back to the app as it's child data changes, and that may or may not be what you want.

Swift - How to add a removed observer in firebase

Issue is resolved not by using addObserver method but by doing this.

  • Created a snapshot class level of var for snapshot

var dataSnapshot: ((DataSnapshot)->Void)?

  • Saved the snapshot

dataSnapshot = { (snapshot: DataSnapshot) in
....
}

  • Set observer using data snapshot

firebaseRef.observe(DataEventType.value, with: dataSnapshot)

  • Removed the observer

firebaseRef?.removeObserver(withHandle: refHandle)

  • When I needed to add the observer again I just started another observer with the same snapshot

  • Set observer using data snapshot

firebaseRef.observe(DataEventType.value, with: dataSnapshot)



Related Topics



Leave a reply



Submit