简体   繁体   中英

Swift - Fetch elements from Firestore

I have a problem with this function:

func fetchGameFromDB(completionHandler: @escaping ([GamesObject]) -> Void) {


    db.collection("games").getDocuments { (querySnapshot, err) in
        if let err = err {
            print("Error: \(err)")
        } else {
            self.gameObject = []
            for document in querySnapshot!.documents {
                print("document \(document.data())")
                if let name = document.data()["name"] as? String {
                    let docRef = self.db.collection("games").document(name)
                    docRef.getDocument { document, error in
                        if let document = document {
                            let data = document.data()
                            let name = data?["name"] as? String ?? ""
                            let urlStanding = data?["urlStanding"] as? String ?? ""
                            let img = data?["gameImg"] as? String ?? ""
                            let urlUpcoming = data?["urlUpcoming"] as? String ?? ""
                            self.gameObject.append(GamesObject(name: name, gameImg: img, urlStanding: urlStanding, urlUpcoming: urlUpcoming))
                            // here i have elements in gameObject
                        }
                        // here i have elements in gameObject
                    }
                    // here gameObject = []
                }
                // here gameObject = []
            }
            completionHandler(self.gameObject)
            // here gameObject = []
        }
    }
}

I get my data well and I add it to my array but when I get to the completionHandler the array is empty.

I find solution, i check if gameObject.count == querySnapshot?.count then I use my completionHandler

func fetchGameFromDB(completionHandler: @escaping ([GamesObject]) -> Void) {
    db.collection("games").getDocuments { (querySnapshot, err) in
        if let err = err {
            print("Error: \(err)")
        } else {
            self.gameObject = []
            querySnapshot?.documents.forEach({ (document) in
                if let name = document.data()["name"] as? String {
                    let docRef = self.db.collection("games").document(name)
                    docRef.getDocument { document, error in
                        if let document = document {
                            let data = document.data()
                            let name = data?["name"] as? String ?? ""
                            let urlStanding = data?["urlStanding"] as? String ?? ""
                            let img = data?["gameImg"] as? String ?? ""
                            let urlUpcoming = data?["urlUpcoming"] as? String ?? ""
                            self.gameObject.append(GamesObject(name: name, gameImg: img, urlStanding: urlStanding, urlUpcoming: urlUpcoming))
                            if self.gameObject.count == querySnapshot?.count  {
                                completionHandler(self.gameObject)
                            }
                        }
                    }
                }
            })
        }
}

}

the first answer there is no problem as long as the missing documents do not exist. but, that cannot be escaped if any of the documents are missing.

how about use to 'DispatchGroup'?

func fetchGameFromDB(completionHandler: @escaping([GamesObject]) -> Void) {

    db.collection("games").getDocuments { (querySnapshot, error) in 
        guard let docs = querySnapshot?.documents, !docs.isEmpty else {
            if let error = error {
                print(error)
            }
            
            return
        }

        let group = DispatchGroup()
        docs.forEach { doc in 
            group.enter()

            guard let name = doc.data()["name"] as? String else {
                group.leave()
                return
            }

            let docRef = self.db.collection("games").document(name)
            docRef.getDocument { document, error in 
                if let document = document, let data = document.data() {

                    //do something...
                    
                    gameObjects.append(GamesObject(...)) //init object
                }
                
                group.leave()       
            }
        }

        group.notify(queue: .main) {
            completionHandler(gameObjects)
        }
    }        
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM