【问题标题】:How do I use DispatchGroup / GCD to execute functions sequentially in swift?如何使用 DispatchGroup / GCD 快速顺序执行函数?
【发布时间】:2018-02-12 05:40:51
【问题描述】:

在刷新我的集合视图之前,我需要依次运行两个函数。第一个函数从 firebase 中提取 autoids 并将它们写入一个数组。然后第二个函数 (getLocation) 使用该数组再次调用 firebase 以检索每个 autoid 下的值(位置)。

我使用 DispatchGroup() 来确保第一个函数在第二个函数开始之前完成。但我还需要在通知刷新集合视图之前完成第二个功能。

我已经编写了一个基本的 for 循环来测试第二个函数中的 DispatchGroup() 并且能够让它执行,但是当我使用它从 firebase 实际获取数据时我无法让它正常工作。

想知道我是否会在错误的地方进出?这是我的功能。

调度组

let dispatchGroup = DispatchGroup()

功能:

 func getLocation() {
        self.dispatchGroup.enter()
        for i in 0..<self.eventsArray.count {
                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)
                    } })
            }
        self.dispatchGroup.leave()
    }


 func getEvents() {

            self.dispatchGroup.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)

                    }
                     self.dispatchGroup.leave()
                } })  
        }

所以我调用每个函数然后使用 dispatchGroup.notify。

  getEvents()
  getLocation()


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

这是我第一次使用 DispatchGroups,因此欢迎任何提示或建议。

【问题讨论】:

标签: swift firebase firebase-realtime-database grand-central-dispatch


【解决方案1】:

当我正确理解您的意图时,您希望:

  • 获取事件 ID
  • 对于每个事件 ID,您想要获取位置

我建议使用两个不同的调度组:

  • 第一个eventDispatchGroup 将在我们获得新事件之前进入,并在所有事件都添加到数组后离开。当这个组收到通知时,所有事件都在数组中,所以我们调用getLocation注意:这个数组会被清除/重置,还是会在后续调用时无限增长,很可能是重复吗?)
  • getLocation 中,我们使用第二个locationDispatchGroup,我们在获取位置之前输入它,并在获取所有位置后离开。收到通知后,该组将更新视图等。(注意:位置数组是否也会在某个时间点被清除?)
  • 调用者只需调用getEvents,然后(在通知块中)调用getLocation

你必须记住的是:

  • DispatchGroup.enter()leave() 调用必须平衡。因此,如果您因某种原因无法确定某个事件的位置,您仍然需要调用 leave(),否则将不会调用 notify()
  • 在处理完所有数据后,始终在观察者代码之外调用enter(),在其内部调用leave()

这是一个可能的解决方案:

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()
        }
    }

}

【讨论】:

  • 谢谢 Andreas doAll() 对我不起作用,我猜这可能是由于它运行 getEvents 然后在 getEvents 函数完成填充位置所依赖的数组之前转到 getLocations在。我正在尝试使用 DispatchQueue。走这条路,是否最好将我的 getEvents 和 getLocations 合并到一个函数中?
  • 嗨@Katie,我刚刚修改了我的答案。请检查一下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-22
相关资源
最近更新 更多