byfu34
byfu34

Reputation: 61

Can't figure out async function call

I'm trying to create a UISearchController to find friends on my app. To populate the array which the search controller is filtering, I'm getting my users' document IDs from Firestore. This uses an asynchronous method getDocuments. I'm trying to use a dispatch group so that my code still runs in the desired order, but it's not working. Here is my function:

func setAllUsers(completion: @escaping ([User]) -> Void) {
        
        let dispatchGroup = DispatchGroup()
        var temp = [String]()
        
        dispatchGroup.enter()
        FirestoreService.db.collection(Constants.Firestore.Collections.users).getDocuments { (snapshot, err) in
            if let err = err {
                print("Error accessing user collection: \(err)")
            } else {
                
                var counter = 0
                
                for doc in snapshot!.documents {
                    counter += 1
                    print("Counter: \(counter)")
                    temp.append(doc.documentID)
                }
            }
            dispatchGroup.leave()
        }
        
        dispatchGroup.notify(queue: .main) {
            completion(UserService.getUserArray(uids: temp))
        }
        
    }

Here is the call in viewDidLoad:

override func viewDidLoad() {
        super.viewDidLoad()
        
        setAllUsers { (users) in
            self.allUsers = users
        }

        print("Number of users in Firestore: \(allUsers.count)")
}

When I run the code, I see this in the console: Number of users in Firestore: 0 Counter: 1 Counter: 2 Counter: 3

How do I fix the order here?

Upvotes: 0

Views: 73

Answers (2)

vadian
vadian

Reputation: 285069

How do I fix the order here?

Very easy, put the line into the closure, it contains the asynchronous code.

setAllUsers { (users) in
    self.allUsers = users
    print("Number of users in Firestore: \(self.allUsers.count)")
}

And you are misusing DispatchGroup, it's not needed

func setAllUsers(completion: @escaping ([User]) -> Void) {
   
    var temp = [String]()
    FirestoreService.db.collection(Constants.Firestore.Collections.users).getDocuments { (snapshot, err) in
        if let err = err {
            print("Error accessing user collection: \(err)")
        } else {
            
            var counter = 0
            
            for doc in snapshot!.documents {
                counter += 1
                print("Counter: \(counter)")
                temp.append(doc.documentID)
            }
           completion(UserService.getUserArray(uids: temp))
        }
        
    }        
}

Upvotes: 1

Frankenstein
Frankenstein

Reputation: 16341

You need to call it inside the closure. Also, you don't need the DispatchGroup.

override func viewDidLoad() {
        super.viewDidLoad()
        
        setAllUsers { (users) in
            self.allUsers = users
            print("Number of users in Firestore: \(allUsers.count)")
            self.tableView.reloadData() // reload the view you're trying to populate with users here.
        }
}

Upvotes: 0

Related Questions