UISearchController取消按钮无法点击问题求助
解决UICollectionViewController本地搜索筛选的问题
我太懂这种查遍问答都解决不了的憋屈了!你想用UISearchController给UICollectionViewController加搜索功能,而且打算自己在当前控制器里处理筛选,把searchResultsController设为nil的思路完全没问题,大概率是某个细节没做对,我给你一套完整的可落地实现,把容易踩的坑也标出来:
核心思路
我们需要维护两个数据源:原始的完整数据、筛选后的结果数据,通过UISearchController的输入回调来更新筛选数据源,然后刷新CollectionView即可。
完整代码实现
首先,你的控制器要遵守UISearchResultsUpdating协议,同时声明两个数据源数组:
class CollectionViewController: UICollectionViewController, UISearchResultsUpdating { // 原始完整数据源 var originalItems: [String] = ["Apple", "Banana", "Cherry", "Date", "Elderberry", "Fig"] // 筛选后的数据源,默认和原始数据一致 var filteredItems: [String] = [] var searchController: UISearchController! override func viewDidLoad() { super.viewDidLoad() // 初始化筛选数据源 filteredItems = originalItems // 初始化搜索控制器,searchResultsController设为nil(关键) searchController = UISearchController(searchResultsController: nil) // 设置当前控制器为搜索结果更新的代理(必须!不然搜索输入没反应) searchController.searchResultsUpdater = self // 搜索时不模糊背景(可选,根据你的UI需求调整) searchController.obscuresBackgroundDuringPresentation = false searchController.searchBar.placeholder = "搜索条目" // 将搜索栏添加到导航栏(也可以加到collectionView的header里) navigationItem.searchController = searchController // 确保搜索栏在当前控制器的生命周期内正确显示(避免跳转后残留) definesPresentationContext = true // 注册CollectionViewCell(根据你的实际cell类型调整) collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "ItemCell") } }
接下来实现CollectionView的数据源方法,注意一定要用筛选后的filteredItems:
// MARK: - UICollectionView 数据源 extension CollectionViewController { override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return filteredItems.count } override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ItemCell", for: indexPath) // 这里给cell添加内容,示例用UILabel显示文本,你可以替换成自己的自定义cell逻辑 if let titleLabel = cell.viewWithTag(101) as? UILabel { titleLabel.text = filteredItems[indexPath.item] } else { let titleLabel = UILabel(frame: cell.bounds.insetBy(dx: 8, dy: 8)) titleLabel.tag = 101 titleLabel.textAlignment = .center titleLabel.text = filteredItems[indexPath.item] cell.backgroundColor = .systemGray6 cell.addSubview(titleLabel) } return cell } }
最后实现搜索更新的核心逻辑,处理输入文本并筛选数据:
// MARK: - UISearchResultsUpdating 协议实现 extension CollectionViewController { func updateSearchResults(for searchController: UISearchController) { // 获取搜索文本,为空时恢复原始数据 guard let searchText = searchController.searchBar.text?.trimmingCharacters(in: .whitespaces), !searchText.isEmpty else { filteredItems = originalItems collectionView.reloadData() return } // 执行筛选逻辑,这里用不区分大小写的包含匹配,你可以改成前缀匹配/正则等 filteredItems = originalItems.filter { item in item.lowercased().contains(searchText.lowercased()) } // 刷新CollectionView显示筛选结果 collectionView.reloadData() } }
容易踩的坑
- 忘记设置
searchResultsUpdater = self:这会导致搜索输入完全没反应,是最常见的错误 - 没设置
definesPresentationContext = true:跳转其他控制器后搜索栏可能会留在屏幕上 - 数据源方法用了原始数组而不是筛选后的数组:搜索时界面完全不变化
- 搜索文本没做去空格处理:输入空格时会出现不符合预期的筛选结果
内容的提问来源于stack exchange,提问作者ajrlewis
相关产品推荐
相关产品推荐

