I tried several times with various ways to assign the collected values of documents from firestore into an array. Unfortunately, I could't find a way to solve this issue. I attached the code that I recently tried to implement. It includes before Firestore closure a print statement which print the whole fetched values successfully. However, after the closure and I tried to print the same array and the result is an empty array.
I tried to implement this code
var hotelCities: [String] = []
func getCities() {
db.collection("Hotels").getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
var found = false
let documentDetails = document.data() as NSDictionary
let location = documentDetails["Location"] as! NSDictionary
let city = location["city"]!
if (self.hotelCities.count == 0) {
self.hotelCities.append(String(describing: city))
}
else{
for item in self.hotelCities {
if item == String(describing: city){
found = true
}
}
if (found == false){
self.hotelCities.append(String(describing: city))
}
}
}
}
print(self.hotelCities)
}
print(self.hotelCities)
}
That's actually the expected result, since data is loaded from Firestore asynchronously.
Once you call
getDocuments()
, the Firestore client goes of and connects to the server to read those documents. Since that may take quite some time, it allows your application to continue running in the meantime. Then when the documents are available, it calls your closure. But that means the documents are only available after the closure has been called.It's easiest to understand this flow, by placing a few print statements:
When you run this code, it will print:
Now when you first saw this code, that is probably not the output your expected. But it completely explains why the
print(self.hotelCities)
you have after the closure doesn't print anything: the data hasn't been loaded yet.The quick solution is to make sure that all code that needs the documents is inside of the close that is called when the documents are loaded. Just like your top
print(self.hotelCities)
statement already is.An alternative is to define your own closure as shown in this answer: https://stackoverflow.com/a/38364861