3
votes

I use a UISearchBar to filter data for a table view and I want the keyboard dismissed when the search bar has no query text (text is removed by tapping the keyboard deleting button or tapping the searchbar clear button). Based on what I've learned about from other posts on stackoverflow, I understand clicking the searchbar clear button (a gray circular button with an x icon) will show the keyboard even if you call searchBar.resignFirstResponder() within the textDidChange UISearchBarDelegate method. So if you click the searchbar clear button, the keyboard will be hidden and then flash back again, while removing text manually will hide the keyboard.

The only solution is to call the resignFirstResponder() method inside the DispatchQueue.main.async code block.

Can anyone explain why you have to call the resignFirstResponder() method asynchronously on the main queue to dismiss the keyboard? why calling it directly does not work?

Check the code below:

    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()
        }
    }
3

3 Answers

1
votes

Simply put, it’s because you can’t make the search bar resign first responder until it has finished talking to you. So you have to wait until the textDidChange delegate method has exited. That is what reentering the main thread asynchronously does.

0
votes

If you were just curious why that happens, @matt is right. In addition to his answer, there is already a UISearchBarDelegate method that triggers when you press cancel button. So you can resign first responder in this method.

func searchBarCancelButtonClicked(_ searchBar: UISearchBar)

I think this can help what you want to achieve.

-1
votes

You can resign responder in endEditing method of a text field delegate methods. that definitely can help you from this problem, but the main UI changes might not be performed in the view. So, for updating UI we need to implement in the dispatch main queue.