iOS中如何用单个UISearchBar同时实现名称与编号搜索
实现UISearchBar双条件(名称/编号)搜索的解决方案
我来帮你搞定这个双条件搜索的需求!首先得指出你现有代码的核心问题:你把名称和编号拆成了两个独立的数组,筛选时只处理了编号数组,没法关联对应的名称。所以第一步要做的是把每条数据的名称和编号绑定在一起,用一个模型类来管理,这样才能同时对两个字段进行筛选。
下面是具体的修改步骤:
1. 创建数据模型类
先定义两个结构体,对应你的JSON数据结构,这样能方便地解析和管理每条用户数据:
// 对应JSON里的顶层结构 struct UserResponse: Codable { let log: [UserData] } // 对应每条用户数据的结构 struct UserData: Codable { let Name: String? let clg_uniq: String? }
2. 替换原有数据数组
把原来的clg_uniq和filteredData换成模型数组,明确数据类型:
let searchBar = UISearchBar() var originalData: [UserData] = [] // 存储从服务器获取的所有原始数据 var filteredData: [UserData] = [] // 存储筛选后的数据 @IBOutlet weak var listTblView: UITableView!
3. 修改JSON解析逻辑
原来的解析只提取了编号,现在要把整个log数组解析成[UserData]:
// 假设你已经获取到了服务器返回的JSON Data对象 do { let decodedResult = try JSONDecoder().decode(UserResponse.self, from: jsonData) self.originalData = decodedResult.log self.filteredData = self.originalData // 初始化筛选数据为全部原始数据 self.listTblView.reloadData() } catch { print("JSON解析失败:\(error.localizedDescription)") }
4. 更新UITableView数据源方法
现在filteredData是模型数组,需要从模型中取出名称和编号显示到cell上,同时处理nil的情况(避免label显示空白或nil):
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return filteredData.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell let currentData = filteredData[indexPath.row] // 处理名称为nil的情况,显示默认文本 cell.userNameLbl.text = currentData.Name ?? "无名称" // 处理编号为nil的情况,显示默认文本 cell.userClgLbl.text = currentData.clg_uniq ?? "无编号" return cell }
5. 修改搜索逻辑,支持双条件筛选
更新searchBar(_:textDidChange:)方法,实现“名称包含搜索文本 或 编号包含搜索文本”的筛选逻辑,同时处理nil字段的情况:
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { // 搜索文本为空时,显示全部数据 guard !searchText.isEmpty else { filteredData = originalData DispatchQueue.main.async { self.listTblView.reloadData() searchBar.resignFirstResponder() } return } // 核心筛选逻辑:只要名称或编号匹配搜索文本,就保留这条数据 filteredData = originalData.filter { userData in // 检查名称是否匹配(忽略大小写),如果名称为nil则不匹配 let nameMatches = userData.Name?.range(of: searchText, options: .caseInsensitive) != nil // 检查编号是否匹配(忽略大小写),如果编号为nil则不匹配 let idMatches = userData.clg_uniq?.range(of: searchText, options: .caseInsensitive) != nil // 两个条件满足其一即可 return nameMatches || idMatches } DispatchQueue.main.async { self.listTblView.reloadData() } }
这样修改后,你的搜索栏就能同时支持名称和编号的搜索了:用户输入名称时,会筛选出名称包含该文本的数据;输入编号时,会筛选出编号包含该文本的数据;甚至输入的文本同时出现在名称和编号里的条目也会被保留。
内容的提问来源于stack exchange,提问作者Naresh
相关产品推荐
相关产品推荐

