Storing asynchronous Cloud Firestore query results in Swift

旧城冷巷雨未停 提交于 2020-01-22 02:18:25

问题


I am working on a simple project using Swift 5, SwiftUI and Firebase which cycles through given ids in an array, searching in the Cloud Firestore database for each id, and appending the corresponding name associated with the id to a new array.

Here is a picture of my database:

For example, I am given an array a few ids, then for each element in the given array, I get the document associated with that id, then print the "firstname" field in that document.

However, I want to store each "firstname" value retrieved into a separate array locally for use later. In Javascript, I know this is done using await and async functions, but I found out through countless hours of troubleshooting that Swift doesn't have async or await.

Here is my code:

func convertToNames(arr: [String]) -> [String]{

    var newArr : [String] = []

      for id in arr {
         let docRef = db.collection("users").document(id)
                 docRef.getDocument { (document, error) in
                     if let document = document, document.exists {
                         let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
                         let data = document.get("firstname") ?? "nil"

                         print("gotten data: \(data)")
                         newArr.append(String(describing: data))

                     } else {
                         print("Document does not exist")
                     }
            }
        }

    print("NEW ARRAY: \(newArr)")
    return (newArr)
}

This code prints an empty array when finished, and I understand why but I just have no clue how to make it work in Swift. I've spent about 5 hours today sifting through the Firebase documentation, looking at example code, and sifting through Youtube, but none of the resources address this issue to the extent that I need. If it is impossible to do, please let me know.


回答1:


You need a dispatch group in addition to a completion

func convertToNames(arr: [String],completion:@escaping(([String]) -> ())) {

    var newArr : [String] = []
    let g = DispatchGroup()
      for id in arr {
         let docRef = db.collection("users").document(id) 
                 g.enter()
                 docRef.getDocument { (document, error) in
                     if let document = document, document.exists {
                         let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
                         let data = document.get("firstname") ?? "nil"

                         print("gotten data: \(data)")
                         newArr.append(String(describing: data))
                         g.leave()
                     } else {
                         print("Document does not exist")
                         g.leave()
                     }
            }
        }

       g.notify(queue:.main) { 
         print("NEW ARRAY: \(newArr)")
         completion(newArr)
       }
}

Call

convertToNames(arr:<#arr#>) { res in
     print(res)
}


来源:https://stackoverflow.com/questions/59482689/storing-asynchronous-cloud-firestore-query-results-in-swift

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