确保Firebase中的asynchronous操作已完成
我需要在swift中对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) } }) } } })
在允许其他操作发生在应用程序之前,如何testing并检查第二个用户usersURL
是否已完成?
完成asynchronous函数的一种方法是使用完成处理程序。 您已经在Firebase API中使用了完成处理程序,并且系统框架中有许多API,因此我不会进一步解释。
给定这种方法,把你的代码包装到一个函数中,比如updateContacts
和一个完成处理程序。 通常一个asynchronous函数返回计算值或错误 。 在某些情况下,它只是成功或失败 – 没有返回值。 你在完成处理程序的签名中expression了这一点。 您的函数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) } }
现在,当你有一个asynchronous子任务的数组时,它将被并行调用,并且当所有的子任务完成时,你想要发信号完成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) }