Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reload data after all Firebase calls finished?

I'm using Firebase (Swift) to read a list of group ids that the user belongs to then looping over the ids to get more info about the groups. Something similar to this (pseudo code):

// List the names of all Mary's groups
var ref = new Firebase("https://docs-examples.firebaseio.com/web/org");
// fetch a list of Mary's groups
ref.child("users/mchen/groups").on('child_added', function(snapshot) {
  // for each group, fetch the name and print it
  String groupKey = snapshot.key();
  ref.child("groups/" + groupKey + "/name").once('value', function(snapshot) {
    System.out.println("Mary is a member of this group: " + snapshot.val());
  });
});

How do I know that all Firebase observeSingleEvent has done executing so I could reload the data in my collection view.

Edit:

After doing more research, this looks very similar to this question. I could use dispatch_group or Bolts framework

Edit 2:

Thanks to @appzYourLife for his answer. I also was able to solve it using RxSwift. I simply wrapped the Firebase calls with observers and saved them in an array then called

Observable.zip(observables, { _ in }).subscribe(onCompleted: {
       self.contentView.collection.reloadData() // do something here
}) 
like image 838
Jimmy Avatar asked Jan 31 '26 10:01

Jimmy


1 Answers

If you want to be notified when all the firebase calls have been completed you can use this code

let ref = FIRDatabase.database().reference()
ref.child("users/mchen/groups").observeSingleEvent(of: .value, with: { snapshot in
    let groupKeys = snapshot.children.flatMap { $0 as? FIRDataSnapshot }.map { $0.key }

    // This group will keep track of the number of blocks still pending 
    let group = DispatchGroup()

    for groupKey in groupKeys {
        group.enter()
        ref.child("groups").child(groupKey).child("name").observeSingleEvent(of: .value, with: { snapshot in
            print("Mary is a member of this group: \(snapshot.value)")
            group.leave()
        })
    }

    // We ask to be notified when every block left the group
    group.notify(queue: .main) {
        print("All callbacks are completed")
    }
})

How does it work?

There are 4 main instructions involved.

  1. First of all we create a group DispatchGroup(). This value will keep track of the number of pending blocks.

    let group = DispatchGroup()
    
  2. Then before starting a new asynchronous call we tell the group there is a new pending block.

    group.enter()
    
  3. Inside the callback closure we tell the group that one block has finished its work.

    group.leave()
    
  4. We tell the block to run a closure when the number of blocks into the group does become zero.

    group.notify(queue: .main) {
        print("All callbacks are completed")
    }
    
like image 173
Luca Angeletti Avatar answered Feb 03 '26 04:02

Luca Angeletti