我使用UISearchBar来筛选表视图的数据,并且当搜索栏没有查询文本时(通过点击键盘删除按钮或点击搜索栏清除按钮来删除文本(,我希望键盘关闭。根据我从stackerflow上的其他帖子中了解到的情况,我知道即使你在textDidChange UISearchBarDelegate方法中调用searchbar.regionFirstResponder((,点击搜索栏清除按钮(一个带有x图标的灰色圆形按钮(也会显示键盘。因此,如果您单击搜索栏清除按钮,键盘将被隐藏,然后再次闪烁,而手动删除文本将隐藏键盘。
唯一的解决方案是在DispatchQueue.main.async代码块内调用辞职FirstResponder((方法。
有人能解释一下为什么你必须在主队列上异步调用辞职FirstResponder((方法来关闭键盘吗?为什么直接调用它不起作用?
检查以下代码:
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchBar.text?.count == 0 {
loadItems()
//the following code works!
DispatchQueue.main.async {
searchBar.resignFirstResponder()
}
// //this line of code only works when you tap the deleting keyboard button to remove the query text
// //does not work if you click the searchbar clear button
// searchBar.resignFirstResponder()
}
}
简单地说,这是因为你不能让搜索栏在与你交谈结束之前辞去第一响应者的职务。因此,您必须等待textDidChange
委托方法退出。这就是异步重新进入主线程的作用。
如果你只是好奇为什么会发生这种情况,@matt是对的。除了他的答案,还有一个UISearchBarDelegate方法,当您按下取消按钮时会触发。所以你可以用这种方法辞去第一响应者的职务。
func searchBarCancelButtonClicked(_ searchBar: UISearchBar)
我认为这可以帮助你实现你想要的目标。
您可以在文本字段委托方法的endEditing方法中放弃响应程序。这肯定可以帮助您解决这个问题,但主UI更改可能不会在视图中执行。因此,为了更新UI,我们需要在调度主队列中实现。