I would like to use asynchronous tasking for my app with using DispatchQueue.global().async and DispatchQueue.main.async, but it doesn't work.
I would like to get the data from firebase and then make List and pass it to closure. But in the code below, the timing completion called is first and then posts.append is called.
func retrieveData(completion: @escaping ([Post]) -> Void) {
var posts: [Post] = []
let postsColRef = db.collection("posts").order(by: "createdAt").limit(to: 3)
postsColRef.getDocuments() { (querySnapshot, error) in
if let error = error {
print("Document data: \(error)")
} else {
DispatchQueue.global().async {
for document in querySnapshot!.documents {
let data = document.data()
let userId = data["userId"] as? String
let postImage = data["postImageURL"] as? String
let createdAt = data["createdAt"] as? String
let docRef = db.collection("users").document(userId!)
docRef.getDocument() { (document, error) in
if let document = document, document.exists {
let data = document.data()!
let userName = data["userName"] as? String
let post = Post(
userId: userId!,
userName: userName!,
postImageURL: postImage!,
createdAt: createdAt!
)
print("When append called")
posts.append(post)
}
}
}
DispatchQueue.main.async {
print("When completion called")
print(posts)
completion(posts)
}
}
}
}
}
I would like to complete for loop at first, and then go to completion. Could anybody give me any idea?