Still learning some swift and managed to advance and retrieving data from a firestore database. I have a Data Controller
whose task is to offload all the data retrieving from firestore. It does the calls and gets data, but when returning the info from the first function I have implemented on it, it's empty.
Here's an example of the funcion:
func fetchUnidades(for foo: MyFirstEnum, and bar: MySecondEnum ) -> [MyClassType]{
let db = Firestore.firestore()
let colPath = "my/firebase/path"
let results = [MyClassType]()
let collection = db.collection(colPath)
collection.whereField("myField", isEqualTo: foo.rawValue).getDocuments() { querySnapshot, err in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
do {
print("\(document.documentID) => \(document.data())") // 1st print
let newMyClass = try document.data(as: MyClassType.self)
results.append(newMyClass)
print("here") // 2nd print - debug breakpoint
}catch (let error) {
print("\(error)")
}
}
}
}
print("DC - Recovered \(results.count) results")
return results
}
Assume MyFirstEnum
, MySecondEnum
and MyClassType
are correct, because the database retrieves info. On the 1st print
line, there's output for data retrieved, and on the 2nd print - debug breakpoint
line, if I do a po results, it has one value, which is the one retrieved as you can see here:
unidades
being the name on my code of results
on this example.
But right after continuing with the execution, unidades
, aka results
is empty, the line:
print("DC - Recovered \(results.count) results")
prints DC - Recovered 0 results
and the return also returns an empty array with zero values on it.
Any idea about why this might be happening? And how to solve the issue? Obviously the goal is to return the info...
CodePudding user response:
That's because the result comes asynchronously. Your fetchUnidades
returns results
array before it's populated.
You need to add a completion
closure in this case. Instead of returning results
you call that completion
closure and pass the results
as its argument.
func fetchUnidades(for foo: MyFirstEnum, and bar: MySecondEnum, completion: (results: [MyClassType]?, error: Error?) -> Void) {
let db = Firestore.firestore()
let colPath = "my/firebase/path"
let collection = db.collection(colPath)
collection.whereField("myField", isEqualTo: foo.rawValue).getDocuments() { querySnapshot, err in
if let err = err {
print("Error getting documents: \(err)")
completion(nil, err)
} else {
let results = [MyClassType]()
for document in querySnapshot!.documents {
do {
print("\(document.documentID) => \(document.data())") // 1st print
let newMyClass = try document.data(as: MyClassType.self)
results.append(newMyClass)
print("here") // 2nd print - debug breakpoint
}catch (let error) {
print("\(error)")
}
}
completion(results, nil)
}
}