Swift 4.2:如何为Codable解析的JSON数组实现全局搜索栏并同步数据?
解决Codable数据配合SearchBar过滤TableView的同步问题
我明白你现在的困扰——已经用Codable把JSON数据加载到TableView了,但添加SearchBar后,不知道怎么让原数据数组和过滤后的数组配合工作,实现搜索过滤功能对吧?下面我一步步帮你调整代码:
步骤1:修正结构体与定义必要变量
首先你需要补全Datum结构体里缺失的createDate类型(根据后续代码使用场景,这里设为String),然后在ViewController中添加过滤数组和搜索状态标记变量:
// 修正后的Datum结构体 struct Datum: Codable { let id, userID, country, card: Int let category: Int let title, description: String let createDate: String // 补充类型定义,否则编译报错 let user: User enum CodingKeys: String, CodingKey { case id case userID = "user_id" case country, card, category, title, description case createDate = "create_date" } } // ViewController中的变量定义 var tableArray: [Datum] = [] // 存储原始JSON数据 var filteredData: [Datum] = [] // 存储搜索过滤后的结果 var isSearching = false // 标记当前是否处于搜索状态
步骤2:修改TableView数据源方法
让TableView根据搜索状态自动切换数据源,这样就能实现原数组和过滤数组的同步展示:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // 搜索状态下返回过滤数组的数量,否则返回原数组数量 return isSearching ? filteredData.count : tableArray.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) as! CustomTableViewCell // 根据搜索状态选择对应的数据源 let item = isSearching ? filteredData[indexPath.row] : tableArray[indexPath.row] cell.name_label.text = "\(item.user.firstname) \(item.user.lastname)" cell.date_label.text = item.createDate return cell }
步骤3:完善SearchBar的过滤逻辑
替换你原来的searchBar(_:textDidChange:)方法,针对Datum类型的数据做精准过滤(这里示例同时搜索用户全名、标题、描述,你可以根据需求调整过滤字段):
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { isSearching = !searchText.isEmpty if isSearching { // 多字段模糊匹配,支持大小写不敏感 filteredData = tableArray.filter { datum in let fullName = "\(datum.user.firstname) \(datum.user.lastname)" let matchesName = fullName.range(of: searchText, options: .caseInsensitive) != nil let matchesTitle = datum.title.range(of: searchText, options: .caseInsensitive) != nil let matchesDescription = datum.description.range(of: searchText, options: .caseInsensitive) != nil return matchesName || matchesTitle || matchesDescription } } else { // 搜索框为空时,过滤数组重置为原数组 filteredData = tableArray } tableView.reloadData() } // 处理取消搜索的逻辑,恢复原数据展示 func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { isSearching = false searchBar.text = "" searchBar.resignFirstResponder() tableView.reloadData() }
步骤4:初始化SearchBar代理
在viewDidLoad中设置SearchBar的代理并启用取消按钮,确保搜索事件能被正确响应:
override func viewDidLoad() { super.viewDidLoad() // 原有初始化代码(比如TableView代理、JSON解析等) searchBar.delegate = self searchBar.showsCancelButton = true }
内容的提问来源于stack exchange,提问作者devmikle
相关产品推荐
相关产品推荐

