为啥必须在主队列上异步调用 resignFirstResponder() 来关闭键盘
Posted
技术标签:
【中文标题】为啥必须在主队列上异步调用 resignFirstResponder() 来关闭键盘【英文标题】:Why have to call resignFirstResponder() asynchronously on the main queue to dismiss the keyboard为什么必须在主队列上异步调用 resignFirstResponder() 来关闭键盘 【发布时间】:2020-03-13 03:35:32 【问题描述】:我使用 UISearchBar 过滤表格视图的数据,并且我希望在搜索栏没有查询文本时关闭键盘(通过点击键盘删除按钮或点击搜索栏清除按钮删除文本)。根据我从 *** 上的其他帖子中了解到的信息,我了解即使您在 textDidChange UISearchBarDelegate 方法中调用 searchBar.resignFirstResponder(),单击搜索栏清除按钮(带有 x 图标的灰色圆形按钮)也会显示键盘。因此,如果您单击搜索栏清除按钮,键盘将被隐藏然后再次闪回,而手动删除文本将隐藏键盘。
唯一的解决方案是调用 DispatchQueue.main.async 代码块中的 resignFirstResponder() 方法。
谁能解释为什么必须在主队列上异步调用 resignFirstResponder() 方法来关闭键盘?为什么直接调用它不起作用?
检查下面的代码:
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()
【问题讨论】:
【参考方案1】:简单地说,这是因为你不能让搜索栏退出第一响应者,直到它完成与你的交谈。所以你必须等到textDidChange
委托方法退出。这就是异步重新进入主线程所做的事情。
【讨论】:
【参考方案2】:如果您只是好奇为什么会这样,@matt 是对的。除了他的回答之外,已经有一个 UISearchBarDelegate 方法在您按下取消按钮时触发。所以你可以用这种方法辞退第一响应者。
func searchBarCancelButtonClicked(_ searchBar: UISearchBar)
我认为这可以帮助您实现想要的目标。
【讨论】:
【参考方案3】:您可以在文本字段委托方法的 endEditing 方法中退出响应者。这绝对可以帮助您解决这个问题,但主要的 UI 更改可能不会在视图中执行。因此,为了更新 UI,我们需要在调度主队列中实现。
【讨论】:
以上是关于为啥必须在主队列上异步调用 resignFirstResponder() 来关闭键盘的主要内容,如果未能解决你的问题,请参考以下文章
为啥 NSManagedObjectContext 队列在主线程上执行?