You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:55:49