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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 03:51:06