在项目中使用了UISearchController,设置导航栏的titleView为searchBar,无意中发现在iOS11和iOS12点击搜索框会崩溃。
崩溃原因
报 unrecognized selector sent to instance
错的原因一般是对象被提前释放,但是我查了控制器所有的引用,没有发现提前释放,并且这报的错是searchController,所以我查了代码,发现一点可疑的地方:
// 需要设置searchTextField的样式和监听方法的地方,iOS13以下使用KVO取到textField
if #available(iOS 13.0, *) {
searchTextField = searchVC.searchBar.searchTextField
} else {
searchTextField = searchVC.searchBar.value(forKey: "_searchField") as? UITextField
}
// 罪魁祸首来了,但是在iOS13上没有问题
searchTextField.delegate = self
为了监听输入框的点击方法,我在这设置了textField代理…如果注释掉这一行,是没有任何问题的,所以进行排查后我发现searchBar有自己的代理对象…(不知道当时写的时候怎么想的,既然有搜索框肯定有封装好的一套代码,不可能直接监听textField的改变啊)
所以把textField代理取消后,设置searchBar的代理方法
searchVC.searchBar.delegate = self
这是 UISearchBarDelegate 的代理方法,完全可以替代 textField 的代理方法,并且使用起来还方便…
@available(iOS 2.0, *)
optional func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool // return NO to not become first responder
@available(iOS 2.0, *)
optional func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) // called when text starts editing
@available(iOS 2.0, *)
optional func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool // return NO to not resign first responder
@available(iOS 2.0, *)
optional func searchBarTextDidEndEditing(_ searchBar: UISearchBar) // called when text ends editing
@available(iOS 2.0, *)
optional func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) // called when text changes (including clear)
@available(iOS 3.0, *)
optional func searchBar(_ searchBar: UISearchBar, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool // called before text changes
@available(iOS 2.0, *)
optional func searchBarSearchButtonClicked(_ searchBar: UISearchBar) // called when keyboard search button pressed
@available(iOS 2.0, *)
optional func searchBarBookmarkButtonClicked(_ searchBar: UISearchBar) // called when bookmark button pressed
@available(iOS 2.0, *)
optional func searchBarCancelButtonClicked(_ searchBar: UISearchBar) // called when cancel button pressed
@available(iOS 3.2, *)
optional func searchBarResultsListButtonClicked(_ searchBar: UISearchBar) // called when search results button pressed
@available(iOS 3.0, *)
optional func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int)
经验
如果使用了UISearchController,一共有三个代理需要绑定:
searchVC.searchResultsUpdater = self
searchVC.searchBar.delegate = self
searchVC.delegate = self
根据业务需要绑定对应的代理