按顺序执行函数调用

时间:2018-06-15 08:43:32

标签: swift asynchronous grand-central-dispatch

每次用户编辑文本字段并根据输入搜索用户时,我都会尝试获取用户输入。在搜索功能的开头,我删除了users数组并执行搜索。但是,该函数被并发调用,甚至在执行搜索之前清空该数组。这可能会导致用户阵列中出现重复数据。有没有办法序列化整个函数调用?我查看了GCD文档并试图实现一些方法,但它没有成功。

这是源代码

 // handles editting movement of the search textfield
@objc func textIsChanging(){
    //need to serialize execution to avoid concurrency.
    // wait until previous call completes? 
    searchUsers()

}

// search user from database.
private func searchUsers(){
    // empty user array and reload table view
    removeUsers()
    if let searchText = searchField.text?.lowercased() {
        // search with starting index..
        Api.User.queryUsersWithStartText(withText: searchText) { (user) in
            if(CurrentUserInfo.uid != user.uid){
                self.users.append(user)
                self.tableView.reloadData()
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

您可以使用DispatchGroup按顺序执行异步功能。您需要确保enter()上的leave()DispatchGroup调用是平衡的,如果您这样做,dispatchGroup.notify(queue: DispatchQueue.main) {...}中的代码只会在当前有阻止的情况下执行可以安全地添加DispatchGroup,因此可以安全地添加另一个块。通过从searchUsers()内部调用dispatchGroup.notify,可以确保只在前一次调用完成执行后调用该函数。

let dispatchGroup = DispatchGroup()

@objc func textIsChanging(){
    dispatchGroup.notify(queue: DispatchQueue.main) {
        searchUsers()
    }
}

// search user from database.
private func searchUsers(){
    dispatchGroup.enter()
    // empty user array and reload table view
    removeUsers()
    if let searchText = searchField.text?.lowercased() {
        // search with starting index..
        Api.User.queryUsersWithStartText(withText: searchText) { (user) in
            if(CurrentUserInfo.uid != user.uid){
                self.users.append(user)
                self.tableView.reloadData()
            }
            dispatchGroup.leave()
        }
    } else {
        dispatchGroup.leave()
    }
}