在具有DispatchGroup的forEach循环内未调用FireBase函数

x8diyxa7  于 2022-09-19  发布在  Swift
关注(0)|答案(1)|浏览(105)

我道歉,如果这个问题是简单的或问题是显而易见的,因为我仍然是编程的初学者。

我正在循环数组,并尝试进行异步FiRestore调用。我使用DispatchGroup是为了在调用Finish之前等待所有迭代完成。

然而,FiRestore函数甚至没有被调用。我使用print语句进行了测试,结果是数组上的循环迭代每次都以Enter进入DispatchGroup,等待停滞。

func getUserGlobalPlays(username: String, fixtureIDs: [Int], completion: @escaping (Result<[UserPlays]?, Error>) -> Void) {    
    let chunkedArray = fixtureIDs.chunked(into: 10)
    var plays: [UserPlays] = []
    let group = DispatchGroup()

    chunkedArray.forEach { ids in

        group.enter()
        print("entered")
        DispatchQueue.global().async { [weak self] in
            self?.db.collection("Users").document("(username)").collection("userPlays").whereField("fixtureID", in: ids).getDocuments { snapshot, error in
                guard let snapshot = snapshot, error == nil else {
                    completion(.failure(error!))
                    return
                }
                for document in snapshot.documents {
                    let fixtureDoc = document.data()
                    let fixtureIDx = fixtureDoc["fixtureID"] as! Int
                    let choice = fixtureDoc["userChoice"] as! Int
                    plays.append(UserPlays(fixtureID: fixtureIDx, userChoice: choice))
                }
                group.leave()
                print("leaving")
            }
        }
    }
    group.wait()
    print(plays.count)
    completion(.success(plays))
}
uqcuzwp8

uqcuzwp81#

我认为您的代码中存在一些问题,您应该进行修复。您正在危险地强行解包文档数据,这是您永远不应该做的。为了在后台调用数据库,您使用了一系列的分派队列,这是不必要的,而且可能会带来问题。数据库调用本身无关紧要,不需要在后台完成。然而,快照返回可以在后台完成(这段代码不能做到这一点,所以如果您愿意的话,可以添加它)。我不知道您希望如何处理这里的错误。如果一个文档返回错误,您的代码也会发回一个错误。这是你想要的处理方式吗?

func getUserGlobalPlays(username: String,
                        fixtureIDs: [Int],
                        completion: @escaping (_result: Result<[UserPlays]?, Error>) -> Void) {
    let chunkedArray = fixtureIDs.chunked(into: 10)
    var plays: [UserPlays] = []
    let group = DispatchGroup()

    chunkedArray.forEach { id in
        group.enter()

        db.collection("Users").document("(username)").collection("userPlays").whereField("fixtureID", in: id).getDocuments { snapshot, error in
            if let snapshot = snapshot {
                for doc in snapshot.documents {
                    if let fixtureIDx = doc.get("fixtureIDx") as? Int,
                       let choice = doc.get("choice") as? Int {
                        plays.append(UserPlays(fixtureID: fixtureIDx, userChoice: choice))
                    }
                }
            } else if let error = error {
                print(error)

                // There was an error getting this one document. Do you want to terminate
                // the entire function and pass back an error (through the completion
                // handler)? Or do you want to keep going and parse whatever data you can
                // parse?
            }
            group.leave()
        }
    }

    // This is the completion handler of the Dispatch Group.
    group.notify(queue: .main) {
        completion(.success(plays))
    }
}

相关问题