0

When my listener is called for my array it returns an empty array instead of the correct elements, why is this?

Model:

    var friendList = [User]()
    var removeFriendListener: ListenerRegistration!

    func addFriendObserver(_ update: @escaping () -> Void) {
        removeFriendListener = CURRENT_USER_FRIENDS_REF.addSnapshotListener{ snapshot, error in
            self.friendList.removeAll()
            
            guard error == nil else {
                #if DEBUG
                    print("Error retreiving collection")
                #endif
                return
            }
            for document in snapshot!.documents {
                let id = document.documentID
                self.getUser(id, completion: { (user) in
                    self.friendList.append(user)
                })
            }
            
            update()
        }
    }

View controller:

    FriendSystem.system.addFriendObserver { () in
        FriendSystem.system.friendList.sort(by: {$0.username < $1.username})
        self.tableView.reloadData()
        print(FriendSystem.system.friendList)
    }
2
  • It seems that getUser is also asynchronous, if that's the case, you should also wait for each and every getUser calls before calling update. Commented Jun 28, 2020 at 18:40
  • @EDUsta And what would the code look like for that? Commented Jun 28, 2020 at 18:52

1 Answer 1

1

It would look like this:

func addFriendObserver(_ update: @escaping () -> Void) {
        removeFriendListener = CURRENT_USER_FRIENDS_REF.addSnapshotListener { snapshot, error in
            self.friendList.removeAll()
            
            guard error == nil else {
                #if DEBUG
                    print("Error retrieving collection")
                #endif
                return
            }
            
            let group = DispatchGroup()

            for document in snapshot!.documents {
                let id = document.documentID
                group.enter()
                self.getUser(id, completion: { (user) in
                    self.friendList.append(user)
                    group.leave()
                })
            }
            
            group.notify(queue: .main) {
                update()
            }
        }
    }

Basically, for every document, a block will enter to the group, which will stay until getUser is completed. After that, when the group is completed, it will notify you, so you can be sure that everything you wanted to be executed is executed.

Edit: Removed dispatchQueue because it is unused, I myself was using it for the notify queue.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.