我需要快速对 Firebase 运行并发查询。如何确保在我的应用程序中允许开始另一个操作之前循环查询已完成?
例如,第一个查询很简单,只是提取数据。但第二个,迭代一个数组,在我的 firebase 数据库中查找某个节点,循环遍历数组 self.contacts
:
// First check if friend, and remove/add to
friendsURL.observeSingleEventOfType(.Value, withBlock: { snapshot in
for oneSnapshot in snapshot.children {
for oneContact in contactsArray {
for oneContactPhoneNum in oneContact.phoneNumbers {
let phoneNumber = oneContactPhoneNum.value as! CNPhoneNumber
contactNumber = phoneNumber.stringValue
// Clean the number
let stringArray = contactNumber!.componentsSeparatedByCharactersInSet(
NSCharacterSet.decimalDigitCharacterSet().invertedSet)
let newString = "1" + stringArray.joinWithSeparator("")
let firebaseFriendNumber = oneSnapshot.value["phoneNumber"] as! String
if newString == firebaseFriendNumber {
self.friends.append(Friend(userName: oneSnapshot.value["userName"] as! String,phoneNumber: firebaseFriendNumber, status: 2, name: oneContact.givenName, userID: oneSnapshot.key))
// Remove that contact
self.contacts.removeObject(oneContact)
}
}
}
}
// Now do the users search:
for oneContact in self.contacts {
for oneContactNumer in oneContact.phoneNumbers {
let phoneNumber = oneContactNumer.value as! CNPhoneNumber
contactNumber = phoneNumber.stringValue
let stringArray = contactNumber!.componentsSeparatedByCharactersInSet(
NSCharacterSet.decimalDigitCharacterSet().invertedSet)
let newString = "1" + stringArray.joinWithSeparator("")
let usersURL: Firebase! = Firebase(url: firebaseMainURL + "presentUserIDUserNameByPhoneNumber/" + newString)
// Check db:
usersURL.observeSingleEventOfType(.Value, withBlock: { snapshot in
if snapshot.childrenCount > 1 {
// They are users (but not your friends):
self.friends.append(Friend(userName: snapshot.value["userName"] as! String, phoneNumber: snapshot.key, status: 1, name: "test", userID: snapshot.value["userID"] as! String))
let userName = snapshot.value["userName"] as! String
print("Friends name: " + userName)
// Remove that contact
self.contacts.removeObject(oneContact)
}
})
}
}
})
在允许应用程序中发生其他操作之前,如何测试和检查 usersURL
上的第二个操作何时完成?
最佳答案
发出异步函数完成信号的一种方法是使用完成处理程序。您已经在 Firebase API 中使用了完成处理程序,并且系统框架中有很多 API,因此我不再进一步解释。
采用这种方法,将您的代码包装到一个函数中,例如带有完成处理程序的 updateContacts
。通常,异步函数返回计算的值或错误。在某些情况下,它只是成功或失败 - 不返回值。您可以在完成处理程序的签名中表达这一点。您的函数 updateContacts
可能不会计算值,但它可能会失败或成功。然后,您可以使用一个可选错误:如果它为nil
,则任务成功,否则包含发生的错误。
当您的基础任务完成后,使用结果调用完成处理程序。
注意:您必须确保完成处理程序最终会被调用!
func updateContacts(completion: (ErrorType?)-> ()) {
friendsURL.observeSingleEventOfType(.Value, withBlock: { snapshot in
...
...
...
usersURL.observeSingleEventOfType(.Value, withBlock: { snapshot in
...
let error = // nil or an error
completion(error)
return
}
completion(nil)
}
}
现在,当您有一组异步子任务时,将并行调用这些子任务,并且您希望在所有子任务完成时发出 updateContacts
完成的信号 - 您可以利用调度组:
let group = dispatch_group_create()
var error: ErrorType?
contactNumbers.forEach { number in
dispatch_group_enter(group)
queryAsync(number) { (result, error) in
if let error = error {
// handle error
} else {
...
}
dispatch_group_leave(group)
}
}
dispatch_group_notify(group, queue) {
// call the completion handler of your function `updateContacts`:
completion(error)
}
关于ios - 确保 Firebase 中的异步操作已完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37150743/