如何在以下代码中从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)
}
}
答案 0 :(得分:2)
你有两个嵌套的异步函数,即favRef.observe
和userRef.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)
}
}
}