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

iOS UITableView搜索数据时选择行出现多选问题的解决方案问询

问题根因

  • 你存储选中状态的selectedIndex是对应当前数据源的行索引,搜索切换为过滤后的searchedText数据源后,原selectedIndex和新数据源的行索引不匹配,导致取消旧选中行时找错/找不到目标行
  • cellForRow中同时存在两种选中判断逻辑(行索引匹配、选中名称匹配),逻辑冲突导致UI展示异常
  • 直接操作cell修改选中图标,没有通过数据源驱动UI刷新,cell复用或列表reload后状态会错乱

修复方案

  1. 统一选中判断逻辑:直接用选中的员工id作为唯一判断标准,不要依赖行索引,避免数据源切换后索引失效的问题
  2. 每次选中新行后刷新列表,所有cell的选中状态基于数据源自动更新,避免直接操作cell的UI
  3. 移除cellForRow中重复的选中状态判断逻辑,简化代码逻辑

修复后的代码实现

extension EmpTableView: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if searching {
            return searchedText.count
        } else {
            return makeList?.count  ?? 0
        }
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomoCell", for: indexPath) as! CustomCell
        let row = indexPath.row
        // 统一获取当前行的员工模型
        let currentEmp: EmpModel? // 替换为你实际的员工模型类名
        if searching {
            currentEmp = searchedText[row]
        }else {
            currentEmp = makeList?[row]
        }
        cell.lblTitle.text = currentEmp?.emp_name ?? ""
        
        // 统一选中状态判断:匹配选中的员工id
        let selectedId = constants.config.selectedArray.count >= 2 ? constants.config.selectedArray[1] : ""
        if currentEmp?.emp_id == selectedId {
            cell.imageSelection.image = #imageLiteral(resourceName: "Selected")
        } else {
            cell.imageSelection.image = #imageLiteral(resourceName: "Unselected")
        }
        return cell
    }
}

extension EmpTableView: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        let row = indexPath.row
        // 获取当前点击的员工模型
        let currentEmp: EmpModel?
        if searching {
            currentEmp = searchedText[row]
        } else {
            currentEmp = makeList?[row]
        }
        guard let emp = currentEmp else { return }
        
        // 取出当前已选中的id
        let selectedId = constants.config.selectedArray.count >= 2 ? constants.config.selectedArray[1] : ""
        
        constants.config.selectedArray.removeAll()
        if emp.emp_id == selectedId {
            // 重复点击选中行,取消选中
            selectedIndex = -1
        } else {
            // 选中新行
            constants.config.selectedArray.append(emp.emp_name ?? "")
            constants.config.selectedArray.append(emp.emp_id ?? "")
            selectedIndex = row
        }
        // 刷新列表,所有cell的选中状态会自动根据数据源刷新
        tableView.reloadData()
        
        self.searchBar.searchTextField.endEditing(true)
    }
}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    if searchText.isEmpty {
        searching = false
        searchedText.removeAll()
    } else {
        searching = true
        searchedText = makeList.filter{$0.emp_name?.range(of: searchText, options: .caseInsensitive) != nil}
    }
    empTable.reloadData()
}

func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
    searchBar.text = ""
}

优化说明

  • 用员工唯一id作为选中状态的判断依据,不受搜索过滤后数据源变化的影响,全量列表和搜索结果列表都能正确识别选中状态
  • 所有UI展示完全由数据源驱动,避免cell复用导致的状态错乱
  • 移除了重复冲突的逻辑,代码可维护性更高

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 14:18:00