How do I use DispatchGroup / GCD to execute functions sequentially in swift?

♀尐吖头ヾ 提交于 2019-12-02 07:44:26

When I understand your intent correctly, you want to:

  • Get event IDs
  • For each event ID, you want to get the Location

I would suggest to use two different dispatch groups:

  • the first, eventDispatchGroup, will enter before we get new events, and will leave after all the events have been added to the array. When this group gets notified, all the events are in the array, so we call getLocation (NOTE: Will this array ever be cleared / resetted, or will it grow unlimitedly upon subsequent calls, likely with duplicates in it?)
  • In getLocation, we use a second locationDispatchGroup that we enter before we get the locations, and leave after all the locations have been fetched. Upon notification, this group will update the view etc. (NOTE: Will the location array also be cleared at some point in time?)
  • The caller will only have to call getEvents, which then (in the notification block) calls getLocation.

What you'll have to keep in mind is:

  • DispatchGroup.enter() and leave() calls have to be balanced. So if you somehow cannot determine the location to some event, you still have to call leave(), otherwise notify() won't be called
  • Always call enter() outside the observer code, and leave() inside of it, after all data has been processed.

Here is one possible solution:

class A {
    var eventDispatchGroup = DispatchGroup()
    var locationDispatchGroup = DispatchGroup()
    var eventsArray = [String]()
    var locationsArray = [String]()

    func getEvents() {
        // clean self.eventsArray here??
        eventDispatchGroup.enter()
        Database.database().reference().child("Events").observe(DataEventType.value, with: { (snapshot) in
            if let dictionary = snapshot.children.allObjects as? [DataSnapshot] {
                for child in dictionary {
                    let eventid = child.key
                    self.eventsArray.append(eventid)
                }
            }
            eventDispatchGroup.leave();
        })
        eventDispatchGroup.notify(queue: .main) {
            getLocation()
        }
    }

    func getLocation() {
        // clean self.locationsArray here?
        for i in 0..<self.eventsArray.count {
            locationDispatchGroup.enter()
            let eventid = self.eventsArray[i]
            self.ref.child("Events").child(eventid).observe(.value, with: { (snapshot) in
                if let dictionary = snapshot.value as? [String: AnyObject] {

                    let location = dictionary["location"] as! String
                    self.locationsArray.append(location)
                }
                locationDispatchGroup.leave()
            })
        }

        locationDispatchGroup.notify(queue: .main) {
            print(self.locationsArray)
            self.eventsCollectionView.reloadData()
        }
    }

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!