Swift completion handler with Firebase

落爺英雄遲暮 提交于 2020-06-11 07:46:27

问题


I am trying to get a list of 'players' from Firebase from the child node 'PlayerInPool' by calling the following functions

func getPlayersInPool(completion: @escaping (_ success: Bool) -> Void) {

    self.handle = self.poolPlayersRef.child(self.pID)observe(.value, with: { snapshot in     

            // Calling the second function
            self.loadPlayersInPool(/*items: items,*/ snapshot: snapshot) { (success) -> Void in

                if success {

                    print("Players Array Count = ", self.players.count)

                    for j in 0 ..< self.players.count {

                        print(self.players[j].description)

                    }
                    //
                    //self.actionController.reloadData()
                    //
                    completion(true)

                }

            }

    }) { (error) in

        print(error.localizedDescription)

    }

}

Second function called from the above function:

func loadPlayersInPool(/*items: [String],*/ snapshot: DataSnapshot, completion: @escaping (_ success: Bool) -> Void) {

    var items: [String] = []

    for item in snapshot.children {

        let user = (item as! DataSnapshot).key

        self.userRef.child(user).child("username").observeSingleEvent(of: .value, with: { (snapshot) in

            let username = snapshot.value

            items.append(username! as! String)

        })

    }

    self.players = items

    // ISSUE HERE THE PLAYER.COUNT IS ALWAYS ZERO (0)!!!!!!!!!
    for j in 0 ..< players.count {

        print(players[j]description)

    }

    completion(true)

}

The issue is that the player array count is always zero (0)!? So I'm not sure if I am using the completion handler correctly?


回答1:


The observeSingleEvent call loads data from the server, so happens asynchronously. This means that your items.append(username! as! String) runs after your call to completion(true).

A simple way to get the behavior you want, is to check if you've loaded all user names by using a simple counter:

func loadPlayersInPool(/*items: [String],*/ snapshot: DataSnapshot, completion: @escaping (_ success: Bool) -> Void) {

    var items: [String] = []

    let loadedCount = 0
    for item in snapshot.children {

        let user = (item as! DataSnapshot).key

        self.userRef.child(user).child("username").observeSingleEvent(of: .value, with: { (snapshot) in

            let username = snapshot.value

            items.append(username! as! String)

            loadedCount++
            if loadedCount == snapshot.childrenCount {
                self.players = items

                for j in 0 ..< players.count {
                    print(players[j]description)
                }

                completion(true)
            }

        })

    }
}


来源:https://stackoverflow.com/questions/52972911/swift-completion-handler-with-firebase

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!