This question already has answers here:
Wait until swift for loop with asynchronous network requests finishes executing
                                
                                    (8个答案)
                                
                        
                                去年关闭。
            
                    
我想通过DispatchQueue.global()。async和DispatchQueue.main.async将异步任务用于我的应用程序,但是它不起作用。

我想从Firebase获取数据,然后制作List并将其传递给闭包。但是在下面的代码中,首先调用的计时完成是然后调用posts.append。

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)
                }
            }
        }
    }
}


我想先完成for循环,然后再完成。有人可以给我任何想法吗?

最佳答案

我只是找到了这个问题(Wait until swift for loop with asynchronous network requests finishes executing)并尝试了下面的代码,它可以正常工作。对每个检查过这个问题的人都感到抱歉。从下一次开始,我将首先搜索现有问题。谢谢。

func retrieveData(completion: @escaping ([Post]) -> Void) {

    var posts: [Post] = []
    let postsColRef = db.collection("posts").order(by: "createdAt").limit(to: 3)
    let group = DispatchGroup()

    postsColRef.getDocuments() { (querySnapshot, error) in
        if let error = error {
            print("Document data: \(error)")
        } else {
            for document in querySnapshot!.documents {
                group.enter()
                let data = document.data()
                let userId = data["userId"] as? String
                let postImage = data["postImageURL"] as? String
                let createdAt = data["createdAt"] as? String
                //投稿に紐づくユーザーデータを取得して合わせてpostArrayに挿入
                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!
                        )
                        posts.append(post)
                        group.leave()
                    }
                }
            }
            group.notify(queue: .main) {
                print(posts)
                completion(posts)
            }
        }
    }
}

关于swift - 想使用DispatchQueue.global()。async和main.async,但效果不佳,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54559014/

10-11 06:15