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

如何在UITableView中基于Model数组实现搜索功能?

解决UISearchBar配合可展开UITableViewCell的搜索与Cell配置崩溃问题

一、梳理数据源与状态管理

先明确核心变量,区分原始数据、搜索结果及展开状态,避免数据混淆:

// 原始全量数据源
var originalData: [YourCurrencyModel] = []
// 搜索结果缓存数组
var searchResults: [YourCurrencyModel] = []
// 标记是否处于搜索模式
var isSearching = false
// 存储已展开的行索引(单组列表场景)
var expandedIndexPaths = Set<IndexPath>()

二、实现UISearchBar的搜索过滤逻辑

通过UISearchBarDelegate方法完成数据过滤,切换搜索状态并刷新表格:

extension YourViewController: UISearchBarDelegate {
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        guard !searchText.trimmingCharacters(in: .whitespaces).isEmpty else {
            // 搜索框为空时恢复原始数据,退出搜索模式
            isSearching = false
            tableView.reloadData()
            return
        }
        // 根据Model字段过滤数据(示例匹配货币全称,按需替换为你的字段)
        searchResults = originalData.filter { model in
            model.currencyNormalFullName.lowercased().contains(searchText.lowercased())
        }
        isSearching = true
        tableView.reloadData()
    }
    
    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searchBar.text = ""
        isSearching = false
        searchResults.removeAll()
        tableView.reloadData()
        searchBar.resignFirstResponder()
    }
}

三、修复Cell配置崩溃问题

直接访问Cell的UI属性崩溃,本质是Cell复用逻辑不严谨或类型转换失败。通过给自定义Cell添加封装的配置方法解决:

1. 给自定义Cell添加配置方法

将UI赋值逻辑封装在Cell内部,避免外部直接操作UI组件:

class ExpandableCurrencyCell: UITableViewCell {
    @IBOutlet weak var currencyNormalFullLabel: UILabel!
    @IBOutlet weak var expandedContentLabel: UILabel!
    
    // 统一配置Cell的方法,传入数据和展开状态
    func configure(with model: YourCurrencyModel, isExpanded: Bool) {
        // 填充基础数据
        currencyNormalFullLabel.text = model.currencyNormalFullName
        // 根据展开状态控制扩展内容显示
        expandedContentLabel.isHidden = !isExpanded
        if isExpanded {
            expandedContentLabel.text = model.expandedDetail // 替换为你的扩展内容字段
        }
    }
}

2. 在cellForRowAt中正确调用配置

确保Cell类型转换安全,再调用配置方法:

extension YourViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return isSearching ? searchResults.count : originalData.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "ExpandableCurrencyCell", for: indexPath) as? ExpandableCurrencyCell else {
            // 转换失败时返回默认Cell,避免崩溃
            return UITableViewCell(style: .default, reuseIdentifier: nil)
        }
        // 获取当前行对应的数据
        let currentModel = isSearching ? searchResults[indexPath.row] : originalData[indexPath.row]
        // 判断当前行是否处于展开状态
        let isExpanded = expandedIndexPaths.contains(indexPath)
        // 调用Cell的配置方法
        cell.configure(with: currentModel, isExpanded: isExpanded)
        return cell
    }
}

四、处理可展开Cell的状态切换

点击Cell时更新展开状态,注意搜索模式下的索引对应搜索结果数组:

extension YourViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        
        if expandedIndexPaths.contains(indexPath) {
            expandedIndexPaths.remove(indexPath)
        } else {
            expandedIndexPaths.insert(indexPath)
        }
        // 刷新当前行,更新展开状态
        tableView.reloadRows(at: [indexPath], with: .automatic)
    }
}

额外注意事项

  • 确保Storyboard/XIB中Cell的复用标识符与代码一致;
  • 过滤逻辑可按需扩展为多字段匹配(如同时匹配货币代码和全称);
  • 若为分组表格,需调整展开状态存储方式(如用[Int: Bool]标记每组是否展开)。

内容的提问来源于stack exchange,提问作者CT4TuEI3

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 10:01:42