iOS 12 使用UISearchController点击搜索框崩溃 _searchController]: unrecognized selector sent to instance

本文介绍了在iOS项目中遇到的一个问题:使用UISearchController时,点击搜索框导致应用崩溃。崩溃原因是由于为textField设置代理导致的。解决办法是取消textField的代理,改为设置searchBar的代理,使用UISearchBarDelegate的方法,从而避免了问题的发生。文章总结了在使用UISearchController时应当注意的代理绑定事项。

在项目中使用了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,一共有三个代理需要绑定:

  1. searchVC.searchResultsUpdater = self
  2. searchVC.searchBar.delegate = self
  3. searchVC.delegate = self

根据业务需要绑定对应的代理

这个错误 `-[__NSTaggedDate count]: unrecognized selector sent to instance 0x8000000000000000` 是 Objective-C 中的一个运行时异常(`NSInvalidArgumentException`),表示你试图向一个对象发送它不支持的消息。 ### 错误解析: - `-[__NSTaggedDate count]`: 表示你调用了 `count` 方法,但接收者是一个 `__NSTaggedDate` 对象。 - `unrecognized selector sent to instance`: 表示该对象没有实现 `count` 方法。 - `0x8000000000000000`: 这是 `NSDate` 的一种优化形式(称为 tagged pointer),用于存储一些简单日期值,不需要分配额外的内存。 ### 常见原因: 你可能将一个 `NSDate` 类型的对象当成了可变集合(如 `NSArray`、`NSDictionary` 或 `NSSet`)来使用,并尝试调用 `count` 方法。例如: ```objective-c NSDate *date = [NSDate date]; NSUInteger length = [date count]; // ❌ 错误!date 不是数组或字典 ``` 你应该检查变量类型是否正确。比如,如果你本意是访问一个数组的长度,但实际传入的是一个 `NSDate`,就会出现这个错误。 ### 解决方法: 1. **确认对象类型**:确保你在调用 `count` 之前对象确实是 `NSArray`、`NSDictionary` 等集合类。 2. **打印对象类型**: ```objective-c NSLog(@"Object class: %@", NSStringFromClass([object class])); ``` 3. **使用类型检查**: ```objective-c if ([object respondsToSelector:@selector(count)]) { NSUInteger count = [object count]; } else { NSLog(@"Object does not respond to 'count'"); } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值