确保异步操作已经完成了火力地堡 [英] Ensuring Async Action Has Completed in Firebase
问题描述
我需要在运行迅速并发查询到火力地堡。我怎样才能确保允许另一个动作之前,我的应用程序启动一个环形查询已完成?
I need to run concurrent queries to Firebase in swift. How can I ensure that a looped query has finished before another action is allowed to start in my app?
例如,第一个查询是一个简单的,简单地提取数据。但第二,通过阵列迭代寻找我的火力点数据库中的某个节点,通过数组 self.contacts
循环:
For example, the first query is a straightforward, and simply pulls data. but the second, iterates through an array looking for a certain node in my firebase database, looping through the array 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
,已完成?
推荐答案
一种方法对信号异步函数完成使用的是完成处理。您已使用完毕处理程序火力地堡API中,有系统的框架大量的API,所以我不认为进一步解释。
One approach to signal completion of an asynchronous function is using a completion handler. You already used completion handlers in the Firebase API and there are many APIs in the system frameworks, so I don't explain that further.
由于这种方法,包住code到一个函数,比如 updateContacts
以完成处理程序。通常一个异步函数的返回计算的值或错误的。在某些情况下,它只是成功或失败 - 不返回值。在完成处理程序的特征码的前preSS这一点。你的函数 updateContacts
可能无法计算的价值,但它可能会失败或成功的反正。然后,您可以使用一个可选的错误:如果是无
,任务成功;否则,它包含发生的错误
Given this approach, wrap your code into a function, say updateContacts
with a completion handler. Usually an asynchronous function returns the computed value or an error. In some cases, it just succeeds or fails - without returning a value. You express this in the signature of the completion handler. Your function updateContacts
may not compute a value, but it may fail or succeed anyway. Then, you can use an optional error: if it is nil
, the task succeeded, otherwise it contains the error that occurred.
当你的基本任务已经完成,与调用的结果完成处理。
When your underlying task has been completed, call the completion handler with the result.
注意:您的必须的保证,即完成处理会的最终名为的
Note: You must ensure, that the completion handler will be eventually called!
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
当所有子任务已经完成 - 你可以利用调度组:
Now, when you have an array of asynchronous subtasks, that will be called in parallel and you want to signal completion of updateContacts
when all subtasks have been completed - you can utilise dispatch groups:
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)
}
这篇关于确保异步操作已经完成了火力地堡的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!