Get all documents at once in a completion handler with getDocuments in Firestore
You only need to enter and leave the dispatch group once for each asynchronous operation. Since (as far as I can see) you only have one getDocuments
call, you should only call enter
and leave
once.
So something like:
let dispatchGroup = DispatchGroup()
var model = [UserModel]()
let db = Firestore.firestore()
let docRef = db.collection("users")
dispatchGroup.enter()
docRef.getDocuments { (querySnapshot, err) in
for document in querySnapshot!.documents {
let dic = document.data()
model.append(UserModel(dictionary: dic))
}
dispatchGroup.leave()
}
...
Swift Completion Handler For Loop to be performed once instead of 10 times due to the loop
Use a DispatchGroup. You can enter the dispatch group each time you call the async code and then leave each time it's done. Then when everything is finished it will call the notify block and you can call your handler. Here's a quick example of what that would look like:
let dispatchGroup = DispatchGroup()
let array = []
for i in array {
dispatchGroup.enter()
somethingAsync() {
dispatchGroup.leave()
}
}
dispatchGroup.notify(queue: .main) {
handler()
}
Firebase / Firestore - completion block not working as expected
First: I think the main issue is because self.isDone = true
is never executed. The reason I think this is because at the time you call fetchData
, nrTotalProduse
will always be 0
, so the execution flow will never enter to the while loop.
Second: You see the cells as they look in the prototypes because numberOfRowsInSection
is being called and returning a number that you set to nrTotalProduse
, but because the isDone
variable is never set to true
, cells are not being set with the corresponding value.
Third: The "buggy" scroll you experience is because what you are calling inside the numberOfRowsInSection
method. This method will be called whenever you call tableView.reloadData
, so what you are doing is keeping a loop of calls that will never end inside this method, resulting in a call to reloadData
such many times that you can even see the scroll.
Totally avoid this kind of calls inside the numberOfRowsInSection
method.
Edit:
If what you are trying to do is get all the documents in the produse
collection, I strongly recommend changing the fetchData
method to something like this:
func fetchData() {
docRef = Firestore.firestore().collection("produse")
docRef.getDocuments() { (querySnapshot, error) in
if let error = error {
print("Error getting documents: \(error)")
} else {
for document in querySnapshot!.documents {
let data = document.data()
let produs = Produs(denumire: (data?["nume"] as? String)!)
self.anunturi.append(produs)
}
self.isDone = true
self.tableView.reloadData()
}
}
}
Is it possible to have a completion block on the firestore query?
You need to put your signIn
INSIDE the getDocuments
handler, probably after the for
loop?
Related Topics
iOS 8 Swift Audio Playback Execute Method on Completion
Linking Error When Building Parse in Xcode 7
Updated Approach to Reauthenticate a User
"Ambiguous Use of 'Children'" When Trying to Use Nstreecontroller.Arrangedobjects in Swift 3.0
How to Stop an Infinitely Rotating Image? and How Does One Implement Removeallanimations
Composing Video and Audio - Video's Audio Is Gone
Empty Class in Swift Playground Gives _Lldb_Expr_ Error
Including Zeros in Front of an Integer
After Getting Image from Uiimagepickercontroller, Uiimageview Rotates Image for iPhone 5
Is There Difference Between Using a Constructor and Using .Init
How to Run App in Simulator Xcode 6
How to Display Mtkview with Rgba16Float Mtlpixelformat
Swift Package Manager with Resources Compile Errors
Differences Between Ways of Initializing a Dictionary
Swift Implement Literalconvertible Protocol