Daibaku
Daibaku

Reputation: 12606

Call DispatchGroup() in the right place

I would like to use DisaptchGroup to call func after iterate through and append elements into array.

here is firebase node looks like

 {
       "tags": {
           "NewYork": {
                 uid1: 1
                 uid2: 1
           }, 
          "baseball": {
                 uid1: 1
           }
        }
    }

So, basically what I'm doing is after user selected tags, fetch uids under the tags and pass those uids to the array.

func filterTempo(filterTag: FilteredTags) {

        let group = DispatchGroup()
        let tag = filterTag.selectedTag.components(separatedBy: "/") //it reutrns "NewYork" and "baseball"

            tag.forEach { (key) in
                self.ref.child("tags").child(key).observe(.value, with: { (snapshot) in
                    guard let dictionary = snapshot.value as? [String:Any] else { return }
                    for (key,_) in dictionary {
                        self.arrays.append(key)
                    }
           // want call func after iteration has finished.
                }, withCancel: nil)
            }
    }//func

After first iteration, array will be like this [uid1, uid2]. Then after second iteration, array will look like this [uid1, uid2, uid1]. I would like to call function( func fetchTeams(array: [String]) ) after iteration has completed not mid-way. To achieve that I tried to use DispatchGroup but I tried print(array) in the func fetchTeams and it returns like so.

[uid1, uid2]
[uid1, uid2, uid1]

Where should I call DispatchGroup.enter() and DispatchGroup.leave() to fix this? Thank you in advance!

Upvotes: 0

Views: 297

Answers (1)

Andreas Oetjen
Andreas Oetjen

Reputation: 10199

You have to call group.enter() everytime just before you call observe. Inside each observe closure, after the work has been done, you call group.leave(). Once the number of enter and leave calls cancel out (e.g. all entered blocks have been left), the queue.notifiy closure will be called, where you then call fetchTerms or something else:

func filterTempo(filterTag: FilteredTags) {

    let group = DispatchGroup()
    let tag = filterTag.selectedTag.components(separatedBy: "/") //it reutrns "NewYork" and "baseball"

        tag.forEach { (key) in
            group.enter()
            self.ref.child("tags").child(key).observe(.value, with: { (snapshot) in
                guard let dictionary = snapshot.value as? [String:Any] else { return }
                for (key,_) in dictionary {
                    self.arrays.append(key)
                }
                group.finished()
            }, withCancel: {
                // Maybe do some error handling here.
                group.finished()
            })
        }
        group.notify(queue: DispatchQueue.main)  {
            // called after all blocks have been finished.
            self.fetchTeams(self.arrays)
        }
}//func

Upvotes: 1

Related Questions