Home > front end >  Removing the Firebase Observer does not work
Removing the Firebase Observer does not work

Time:11-29

I load some data to show them on a tableView. I try to remove the observer for this. Right now the observer shows duplicate content. It shows the a post 10-15 times.

This is how I observe:

   func loadData(){
        let placeIdFromSearch = ViewController.placeidUebertragen
        ref = Database.database().reference().child("placeID/\(placeIdFromSearch)/\(ViewComments.subComment)/subcomment/")
        
        ref.observe(.childAdded) { (snapshot) in
            
            print("something changed")
            guard let dic = snapshot.value as? [String: Any] else { return }
            let newPost = importSubPosts(dictionary: dic, key: snapshot.key)
            guard let userUid = newPost.userID else { return }
            self.fetchUser(uid: userUid, completed: {
                self.table.insert(newPost, at: 0)
                self.tableView.reloadData()
            })
        }

    }

    func fetchUser(uid: String, completed: @escaping () -> Void) {
        ref = Database.database().reference().child("user").child(uid)
        ref.observe(.value) { (snapshot) in
            guard let dic = snapshot.value as? [String: Any] else { return }
            let newUser = UserModel(dictionary: dic)
            self.users.insert(newUser, at: 0)
            completed() 
        }
    }

This should remove the observer:

ref = Database.database().reference().child("placeID/\(placeIdFromSearch)/\(ViewComments.subComment)/subcomment/")
ref.removeAllObservers()

But nothing happens.

PS: If it helps if I deactivate this part the error goes away. But then I don't have user profile picture. Is It because I use this func already on a different tableView?

ref.observe(.value) { (snapshot) in
            guard let dic = snapshot.value as? [String: Any] else { return }
            let newUser = UserModel(dictionary: dic)
            self.users.insert(newUser, at: 0)

CodePudding user response:

The Firebase documentation provides a number of examples of how to read and write data

In this case it appears there are a couple of issues;

One is how to implement listeners:

.childAdded - This event is triggered once for each existing child and then again every time a new child is added to the specified path

ChildAdded is great for initially loading a list of data e.g. several child nodes and watching for additions to that list thereafter. If you want to load the data and then stop listening, you can remove the listener from inside the .childAdded closure (there are other options as well)

If you're interested in loading just a single node, 'subcomment' see the load single node section below

If, however subcomment should be plural 'subcomments' because there are several, you can user this pattern to load them without leaving an observer

let usersRef = my_firebase.child("users")
usersRef.observeSingleEvent(by: .value, with: { snapshot in
    //all users are returned to the app in the snapshot
    //   .value means 'give me everything in the specified node'
    // so then we can iterate over the snapshot to get each users data
}
  • Load single node -

The second issue which ties to the first issue within the 'fetchUser' function - it appears you want to read in a single user from Firebase, one time.

While you can use .observe to do that, it actually reads in ALL data and listens for all events ongoing which doesn't appear like you want to do.

A better solution is to read the user one time with observeSingleEvent aka getData that reads it in and doesn't leave a listener - therefore eliminating the need to remove observers when the read is done.

There's a perfect example in the documentation that you could almost copy and paste the code - it reads a single user, and doesn't leave an observer. It could be used for reading the subcomment as well without leaving a listener attached. See the code at Read Data Once

ref.child("users/\(uid)/username").getData(completion:  { error, snapshot in
  guard error == nil else {
    print(error!.localizedDescription)
    return;
  }
  let userName = snapshot.value as? String ?? "Unknown";
});
  • Related