I'm trying to use DispatchQueue to get my code to wait until a query retrieves the results I need from Cloud Firestore before it continues executing, but just haven't been able to get it to work. In the code below I am trying to get it to wait until the data has been retrieved and stored in the zoneMarkerArray, and then print out the result.
I've numbered each line it prints in the order that I want it to happen, and as you'll see in the output it is not waiting for the Firestore result before moving on.
Here is my code:
let zones = self.db.collection("zones")
let zonesQuery = zones.whereField("start", isGreaterThan: lowerLimit).whereField("start", isLessThan: upperLimit)
print("1. zones Query has been defined")
//pass zonesQuery query to getZoneMarkers function to retrieve the zone markers from Firestore
getZoneMarkers(zonesQuery)
print("6. Now returned from getZoneMarkers")
func getZoneMarkers(_ zonesQuery: Query) -> ([Double]) {
print("2. Entered getZoneMarkers function")
DispatchQueue.global(qos: .userInteractive).async {
zonesQuery.getDocuments() { (snapshot, error) in
if let error = error {
print("Error getting zone markers: \(error)")
} else {
print("3. Successfully Retrieved the zone markers")
var result: Double = 0.0
for document in snapshot!.documents {
print("Retrieved zone marker is \(document["start"]!)")
self.zoneMarkerArray.append(document["start"]! as! Double)
print("4. Looping over zone marker results")
}
}
}
DispatchQueue.main.async {
//I want this the printCompleted function to print the result AFTER the results have been retrieved
self.printCompleted()
}
}
return self.zoneMarkerArray
}
func printCompleted() {
print("5. Looping now completed. Result was \(zoneMarkerArray)")
}
And here is the output that prints out:
- zones Query has been defined
- Entered getZoneMarkers function
- Now returned from getZoneMarkers
- Looping now completed. Result was [0.0]
- Successfully Retrieved the zone markers
- Looping over zone marker results
- Looping over zone marker results Retrieved zone marker is 12.0
- Looping over zone marker results
Thanks for the help!
EDIT: In case anyone else out there is also struggling with this, here's the working code I put together in the end based on the feedback I received. Please feel free to critique if you see how it could be further improved:
let zones = self.db.collection("zones")
let zonesQuery = zones.whereField("start", isGreaterThan: lowerLimit).whereField("start", isLessThan: upperLimit)
print("1. zones Query has been defined")
//pass zonesQuery query to getZoneMarkers function to retrieve the zone markers from Firestore
getZoneMarkers(zonesQuery)
func getZoneMarkers(_ zonesQuery: (Query)) {
print("2. Entered getZoneMarkers function")
zoneMarkerArray.removeAll()
zonesQuery.getDocuments(completion: { (snapshot, error) in
if let error = error {
print("Error getting zone markers: \(error)")
return
}
guard let docs = snapshot?.documents else { return }
print("3. Successfully Retrieved the zone markers")
for document in docs {
self.zoneMarkerArray.append(document["start"]! as! Double)
print("4. Looping over zone marker results")
}
self.completion(zoneMarkerArray: self.zoneMarkerArray)
})
}
func completion(zoneMarkerArray: [Double]) {
print("5. Looping now completed. Result was \(zoneMarkerArray)")
}