Metin
Metin

Reputation: 184

Swift - Problem While Downloading Data From Firebase Firestore Asynchronously with DispatchGroup()

While getting every document's ID in the "events" collection where their EventStatus value is equal to 0 and storing them in a string array (documentIds), I tried to run code asynchronously with DispatchGroup() so when I returned "documentIds", I would return a non-empty and complete value.

But when I run the code as it is below, it froze and in fact it never ran in the getDocuments{} closure.

I tried to run getDocuments{} closure in DispatchQueue.global().async{} but it didn't work also.

func someFunction() -> [String] {

var documentIds : [String]!
var dispatchGroup = DispatchGroup()
dispatchGroup.enter()

Firestore.firestore().collection("events").whereField("EventStatus", isEqualTo: 0).getDocuments { (snap, error) in

        if let error = error {
            print(error.localizedDescription)
            return
        }

        guard let snap = snap else { return }

        documentIds = snap.documents.map({ (document) -> String in
            return document.documentID
        })

        dispatchGroup.leave()

    }

dispatchGroup.wait()
return documentIds

}

When it froze, firebase gave this error in the debug console:

"Could not reach Cloud Firestore backend. Backend didn't respond within 10 seconds. This typically indicates that your device does not have a healthy Internet connection at the moment. The client will operate in offline mode until it is able to successfully connect to the backend."

Other than that, no error or some other feedback. Am I doing something wrong with DispatchGroup() or Firestore?

Thanks for your help in advance!

Upvotes: 0

Views: 519

Answers (1)

Robert Dresler
Robert Dresler

Reputation: 11200

This is one of the cases where dispatchGroup is useless and causes many errors.

Since retrieving data from Firestore is async call, use completion handler for your method instead of returning value and get rid of dispatchGroup

func someFunction(completion: @escaping ([String]) -> Void) {

    Firestore.firestore().collection("events").whereField("EventStatus", isEqualTo: 0).getDocuments { snap, error in

        if let error = error {
            print(error.localizedDescription)
            return
        }

        guard let snap = snap else { return }

        var documentIds = snap.documents { document in
            return document.documentID
        }

        completion(documentIds)
    }

}

then call your method with completion handler where you have access to received array of String

someFunction { documentIds in // name completion parameter of type `[String]`
    ... // assign some global array as `documentIds` and then reload data, etc.
}

Upvotes: 3

Related Questions