i'm try to run my function in order to to download some realtime database data change from firebase cloud firestore.
the problem is the my closure onSuccess fire to early, and the array in the closure is always empty.
how can I handle the order of execution in order to execute the closure on success only after the forEach()
after reading online I come up with some queue , but i'm not sure if i'm using correctly.
below my code:
func getuserConfirmFriend(userLoggato: UserModel, onSuccess: @escaping([UserModel]) -> Void, onError: @escaping(_ errorMessage: String) -> Void, newPendingUser: @escaping(UserModel) -> Void, userRemoved: @escaping(UserModel) -> Void , listener: @escaping(_ listenerHandle: ListenerRegistration) -> Void){
let queue = OperationQueue()
let listenerRegistration = db.collection("user").document(userLoggato.userID).collection("confirmFriend").addSnapshotListener(includeMetadataChanges: true) { documentSnapshot, error in
var userConfirmFriendsArray = [UserModel]()
guard let snapshot = documentSnapshot else { return }
let operation1 = BlockOperation {
snapshot.documentChanges.forEach { (documentChange) in
switch documentChange.type {
case .added :
let dict = documentChange.document.data()
let name = dict["name"] as? String ?? "na name"
let surname = dict["surname"] as? String ?? "na name"
let email = dict["email"] as? String ?? "na name"
let userLevel = dict["adminLevel"] as? String ?? "unable to get admin level"
let idUser = dict["userID"] as? String ?? "no ID"
let position1 = dict["position"] as? String ?? "na preferance position"
let position2 = dict["position2"] as? String ?? "na preferance position"
let vote = dict["vote"] as? Int ?? 0
self.downloadImageForAdmin(userID: idUser) { (urlImage) in
let utente = UserModel(name: name, surname: surname, email: email, userID: idUser, adminLevel: userLevel, immagine: urlImage, position: position1, position2: position2, vote: vote)
newPendingUser(utente)
userConfirmFriendsArray.append(utente)
// onSuccess(userConfirmFriendsArray)
}
print("CONFIRM User Added")
case .modified :
//implements action (new escaping)
print("CONFIRM User Modified ")
case .removed :
print("CONFIRM User Removed")
let dict = documentChange.document.data()
let name = dict["name"] as? String ?? "na name"
let surname = dict["surname"] as? String ?? "na name"
let email = dict["email"] as? String ?? "na name"
let userLevel = dict["adminLevel"] as? String ?? "unable to get admin level"
let idUser = dict["userID"] as? String ?? "no ID"
let position1 = dict["position"] as? String ?? "na preferance position"
let position2 = dict["position2"] as? String ?? "na preferance position"
let vote = dict["vote"] as? Int ?? 0
self.downloadImageForAdmin(userID: idUser) { (urlImage) in
let utente = UserModel(name: name, surname: surname, email: email, userID: idUser, adminLevel: userLevel, immagine: urlImage, position: position1, position2: position2, vote: vote)
userRemoved(utente)
}
}
}
}
let operation2 = BlockOperation{
DispatchQueue.main.async {
onSuccess(userConfirmFriendsArray)
}
}
queue.addOperation(operation1)
queue.addOperation(operation2)
}
listener(listenerRegistration)
}
my problem is userConfirmFriend is always empty, even if the code execute first operation1 and then 2
not so familiar with dispatch queue.
thanks