确保Firebase中的异步操作已完成

时间:2016-05-10 23:45:20

标签: ios swift asynchronous firebase

我需要在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)

                            }

                        })

                    }

                }

            })

如何在允许在应用中执行其他操作之前测试并检查usersURL上的第二个已完成的时间?

1 个答案:

答案 0 :(得分:4)

一种异步函数信号完成的方法是使用完成处理程序。您已经在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)
}