在数据加载之前调用完成处理程序

时间:2018-01-21 10:16:30

标签: swift firebase-realtime-database grand-central-dispatch

如何在以下代码中从firebase加载数据之前阻止调用完成处理程序?

我的问题: 在将任何用户附加到用户数组之前调用完成。如果completion实际上已将用户附加到其后,我该如何致电users

我是否必须使用Grand Central Dispatch?

如果您可以像我5岁那样向我解释这一点,那么可以获得积分。旧的,所以我可以停止面对这个问题。

class func fetchFavorites(userId: String, completion: @escaping ([User]) -> Swift.Void) {
    let userRef = Database.database().reference().child("users")
    let favRef = Database.database().reference().child("favorites").child(userId)

    favRef.observe(.value) { snap in
        var users: [User] = []
        for item in snap.children.allObjects as! [DataSnapshot] {
            userRef.child(item.key).observeSingleEvent(of: .value) { snapshot in
                if let dictionary = snapshot.value as? [String:Any] {
                    let newUser = User(dictionary: dictionary)
                    users.append(newUser)
                }
            }
        }
        completion(users)
    }
}

1 个答案:

答案 0 :(得分:2)

你有两个嵌套的异步函数,即favRef.observeuserRef.child().observeSingleEvent(of:),因此问题是在更新用户的所有异步调用完成执行之前,在外部闭包中调用completion

一旦所有异步方法调用在循环中完成执行,您可以使用DispatchGroup并仅调用completion来解决此问题。这可以通过向DispatchGroup添加所有异步调用,然后在completion调用中调用group.notify来实现。

class func fetchFavorites(userId: String, completion: @escaping ([User]) -> Swift.Void) {
    let userRef = Database.database().reference().child("users")
    let favRef = Database.database().reference().child("favorites").child(userId)
    let usersGroup = DispatchGroup()

    favRef.observe(.value) { snap in
        var users: [User] = []
        for item in snap.children.allObjects as! [DataSnapshot] {
            usersGroup.enter()
            userRef.child(item.key).observeSingleEvent(of: .value) { snapshot in
                if let dictionary = snapshot.value as? [String:Any] {
                    let newUser = User(dictionary: dictionary)
                    users.append(newUser)
                }
                usersGroup.leave()
            }
        }
        usersGroup.notify(queue: DispatchQueue.global()){
            completion(users)
        }
    }
}