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

Swift 在加载数据之前调用完成处理程序,swift,firebase-realtime-database,grand-central-dispatch,Swift,Firebase Realtime Database,Grand Central Dispatch,在以下代码中从firebase加载数据之前,如何防止调用完成处理程序 我的问题: 在将任何用户追加到用户数组之前调用Completion。只有在users实际添加了用户之后,我如何调用completion 我必须使用中央调度中心吗 如果你能像我5岁一样向我解释这一点,那么我就可以不再面对这个问题了 class func fetchFavorites(userId: String, completion: @escaping ([User]) -> Swift.Void) { let

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

我的问题: 在将任何用户追加到用户数组之前调用Completion。只有在
users
实际添加了用户之后,我如何调用
completion

我必须使用中央调度中心吗

如果你能像我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)
    }
}

您有两个嵌套的异步函数,即
favRef.observe
userRef.child().observeSingleEvent(of:)
,因此问题是在外部闭包中调用
completion
,然后更新用户的所有异步调用才能完成执行

您可以通过使用
DispatchGroup
解决此问题,并且在所有异步方法调用完成循环中的执行后,只调用
completion
。这可以通过将所有异步调用添加到
调度组
,然后在
组内调用
完成
。通知
调用来实现

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)
        }
    }
}

您有两个嵌套的异步函数,即
favRef.observe
userRef.child().observeSingleEvent(of:)
,因此问题是在外部闭包中调用
completion
,然后更新用户的所有异步调用才能完成执行

您可以通过使用
DispatchGroup
解决此问题,并且在所有异步方法调用完成循环中的执行后,只调用
completion
。这可以通过将所有异步调用添加到
调度组
,然后在
组内调用
完成
。通知
调用来实现

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)
        }
    }
}

您的
completion()。你能在代码中澄清一下吗?你的
completion()
favRef.observe(.value){}
上被异步调用,这没关系,但是
userRef.child(item.key)。observeSingleEvent(of:.value){}
也是异步的,这是你的问题。谢谢你的回复,但我不确定我是否遵循了。你能用代码说明吗?