Swift:在下一次加载之前等待Firestore加载

时间:2018-08-01 17:32:06

标签: swift firebase google-cloud-firestore

我有一个视图控制器,列出了Firestore数据库中的数据。在firestore集合中,我有一堆文档,其信息如列表所示,还有一个名为order的文档,其中包含一个字段,该字段是按希望显示的顺序排列的字符串数组。我的代码抓住了这个:

self.db.collection("officers").document(school).collection(grade).document("order").getDocument {(document, error) in
   if let document = document, document.exists {
     self.officerNames = (document.data()!["order"] as! Array<String>)

,然后应该使用数组orderofficerNames)中的字符串来查询同一集合中的文档(所有文档都具有不同的role,因此只会快照中的一个文档),并以与orderofficerNames)中的文档相同的顺序显示它们。

for item in 1...self.officerNames.count {
    self.db.collection("officers").document(school).collection(grade).whereField("role", isEqualTo: self.officerNames[item-1]).getDocuments() { (querySnapshot, err) in
       if let err = err {
          print("Error getting documents: \(err)")
       } else {
          for document in querySnapshot!.documents {
              let officerMessage = document.data()["agenda"] as! String
              let officerInfo = document.data()["short"] as! String
              (a bunch of code here using that ^ ^ and due to the color I need item to be an integer)
          }
       }
    }
}

我知道,如果我尝试在item之前打印self.collection("officers").....,数字将加一,但是如果我在for document in querySnapshot.....中进行打印,则它们将全部乱序,这意味着某些文档已加载得比别人快。我已经读过Swift中的Async函数(尽管我确实在JavaScript中使用过这些函数),但实际上对如何使用它们感到困惑,希望有一种更简单的方法可以做到这一点。在再次遍历循环之前,我可以等待任何方法来确保已加载并分析了先前的文档吗?

这是数据库的屏幕截图: enter image description here

enter image description here

1 个答案:

答案 0 :(得分:0)

老实说,您可能想检查一下数据结构,看是否可以创建一个不需要多个查询的数据结构。我还不太清楚您的数据结构是什么,但是如果您更新问题以包含它,我可以为如何重构提供一些建议,这样您就不必执行2个不同的get请求。

话虽这么说,由于Swift没有像JS这样的承诺,所以很难保证数据井井有条。正如我在this blog中所写,在大多数情况下,闭包都可以正常工作。但是它们仍然不会在异步调用数组中保留顺序。假设您使用某个数组存储警官的数据,则可以通过为每个数组指定一个默认值来预先声明数组的大小。看起来像这样:

var officerArray = [Officer](repeating:Officer(), count: self.officerNames.count)

当然,这取决于您使用哪种对象填充它。在这种情况下,我正在使用一些通用的Officer对象。

然后,不要将新创建的Officer对象(或任何您要调用的对象)附加到数组的末尾,而是将其值添加到数组中的特定位置。

for item in 1...self.officerNames.count {
    self.db.collection("officers").document(school).collection(grade).whereField("role", isEqualTo: self.officerNames[item-1]).getDocuments() { (querySnapshot, err) in
       if let err = err {
          print("Error getting documents: \(err)")
       } else {
          for document in querySnapshot!.documents {
              let officerMessage = document.data()["agenda"] as! String
              let officerInfo = document.data()["short"] as! String
              // etc
              officerArray[self.officerNames.count-1] = Officer(officerMessage: officerMessage, officerInfo: officerInfo) // or however you're instantiating your objects
          }
       }
    }
}

这将保留订单。