如何为含自定义数据模型数组的TableView添加SearchBar
为自定义数据模型的TableView实现搜索功能
核心思路
保留完整的原始数据数组,维护一个过滤后的数组用于TableView展示,通过UISearchBar的代理方法监听搜索输入,实时过滤数据并刷新表格。
具体实现步骤
1. 调整数据存储变量
在SecondViewController中新增两个数组,分别存储所有原始数据和过滤后的数据:
class SecondViewController: UIViewController { // ... 其他已有的变量 var allSurahs = [Datum]() // 存储所有原始数据 var filteredSurahs = [Datum]() // 存储过滤后的数据 // ... }
同时修改callingSurah方法,将解码后的数据赋值给原始数组,并初始化过滤数组:
DispatchQueue.main.async{ self.activityIndicator.stopAnimating() self.activityIndicator.hidesWhenStopped = true self.allSurahs = decoder.data self.filteredSurahs = self.allSurahs // 初始状态显示全部数据 self.tableView.reloadData() }
2. 设置SearchBar代理
在viewDidLoad中添加代理绑定,可选开启取消按钮优化交互:
override func viewDidLoad() { super.viewDidLoad() // ... 其他已有代码 searchBar.delegate = self searchBar.showsCancelButton = true // 显示取消按钮,方便用户快速清空搜索 }
3. 实现UISearchBarDelegate代理方法
给SecondViewController添加代理扩展,处理搜索文本变化和取消操作:
extension SecondViewController: UISearchBarDelegate { // 实时监听搜索框文本变化,过滤数据 func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { if searchText.isEmpty { filteredSurahs = allSurahs } else { // 同时匹配英文名称和翻译,不区分大小写 filteredSurahs = allSurahs.filter { surah in surah.englishName.lowercased().contains(searchText.lowercased()) || surah.englishNameTranslation.lowercased().contains(searchText.lowercased()) } } tableView.reloadData() } // 点击取消按钮,重置搜索状态 func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { searchBar.text = "" filteredSurahs = allSurahs tableView.reloadData() searchBar.resignFirstResponder() // 收起键盘 } }
4. 修改TableView数据源方法
将所有依赖原始数组的数据源方法,替换为使用过滤数组:
extension SecondViewController: UITableViewDelegate, UITableViewDataSource{ func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return filteredSurahs.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let cell = tableView.dequeueReusableCell(withIdentifier: "SurahsViewCell", for: indexPath) as? SurahsViewCell else { return UITableViewCell() } let surah = filteredSurahs[indexPath.row] cell.englishName.text = surah.englishName cell.engTrans.text = surah.englishNameTranslation return cell } // 修正didSelectRowAt方法,使用过滤数组获取数据 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { guard let vc = storyboard?.instantiateViewController(withIdentifier: "AyahController") as? AyahController else {return} vc.surahNumber = filteredSurahs[indexPath.row].number navigationController?.pushViewController(vc, animated: true) } // heightForRowAt方法保持不变 func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 100 } }
关键说明
- 用
lowercased()实现不区分大小写的搜索,提升用户体验 - 保留原始数据数组避免重复请求或解码,保证搜索效率
- 取消按钮配合收起键盘的操作,优化交互流畅度
内容的提问来源于stack exchange,提问作者Ayaan Khan
相关产品推荐
相关产品推荐

