1

I have the below fetch function. How can I add a completion block so when it finishes I can do something?

This query will run the code inside more than once.

func getFollowers() {
    print("get followers called")
    let ref = Database.database().reference()
    ref.child("users2").child((Auth.auth().currentUser?.uid)!).child("Following").observe(.childAdded) { (snap) in
        let personBeignFollow = snap.key
        self.peopleUserFollows.append(personBeignFollow)
        print("Appened: ", personBeignFollow)
        self.fetchAllUserFirstPostMedia(user: personBeignFollow)
    }
}

I have looked here but was not able to make it work.

Here is what I tried:

    func getFollowers(_: ()-> ()) {
    print("get followers called")
    let ref = Database.database().reference()
    ref.child("users2").child((Auth.auth().currentUser?.uid)!).child("Following").observe(.childAdded) { (snap) in
        let personBeignFollow = snap.key
        self.peopleUserFollows.append(personBeignFollow)
        print("Appened: ", personBeignFollow)
        self.fetchAllUserFirstPostMedia(user: personBeignFollow)
    }
}

Then where it is called:

getFollowers() {
   self.collectionView.reloadData()
}

1 Answers1

0

In your function declaration, you can add the following:

func getFollowers(_ completion: @escaping () -> Void) {
    print("get followers called")
    let ref = Database.database().reference()
    ref.child("users2").child((Auth.auth().currentUser?.uid)!).child("Following").observe(.childAdded) { (snap) in
        let personBeignFollow = snap.key
        self.peopleUserFollows.append(personBeignFollow)
        print("Appened: ", personBeignFollow)
        self.fetchAllUserFirstPostMedia(user: personBeignFollow)

       // tell the calling function to execute the completion handler again
       completion()
    }
}

then to use it you would do something like this:

getFollowers {
 // whatever you want to do after the query has run
}

This doesn't directly matter but just as a common design practice, it would be a good idea to pass your new data you retrieved from the query as a parameter in the completion handler rather than assigning a property on the class.

That would look something like this:

func getFollowers(_ completion: (String) -> Void) {
    ref.child("users2").child((Auth.auth().currentUser?.uid)!).child("Following").observe(.childAdded) { (snap) in
        let personBeignFollow = snap.key
        print("Appened: ", personBeignFollow)        
       // tell the calling function to execute the completion handler again
       completion(personBeignFollow)
    }
}

and then your calling site might look like this:

getFollowers { newUser in
    self.fetchAllUserFirstPostMedia(user: newUser)
}
sanch
  • 696
  • 1
  • 7
  • 21
  • Would this not then run 8 times if there are 8 items at the location of the query? –  Apr 09 '19 at 03:08
  • @NCT127 yes it would. `.childAdded` will fire once for every existing item at that location and then once for each item added after your function was called – sanch Apr 09 '19 at 03:11
  • But I want to call reload data once ALL data has been fetched and the firebase call has finished. That is what I would like to achive –  Apr 09 '19 at 03:13
  • @NCT127 if you want to avoid that function being called n times for n existing items, you can use the `.observeSingleEvent(of: .value)` function. this will look at that location *one* time and then return to you everything that lives at the specified location. – sanch Apr 09 '19 at 03:15
  • So is that the best way to do this? to use that and then loop through the items I need? How exactly would that look if it is teh correct solution? –  Apr 09 '19 at 03:16
  • @NCT127 Well you have to consider how often that data is going to be changing and more importantly how important it is for the user to see the updates without them reloading the view. So what you would do is iterate over the dictionary items and manipulate them however you want. check this out: https://stackoverflow.com/questions/27341888/iterate-over-snapshot-children-in-firebase/27342233 – sanch Apr 09 '19 at 03:22
  • @NCT127 please mark the answer as correct if your original question was answered – sanch Apr 09 '19 at 03:24