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

UISearchController问题:筛选后选中项索引与原始数组不匹配

问题分析与解决方案

嘿,这个问题我太熟啦!你遇到的核心问题是筛选状态下的索引不匹配——当你在搜索筛选后点击行时,你用的是筛选后数组的索引去操作原始数组,这就导致修改错了元素。

问题根源

看你的didSelectRowAt方法:

let accessoryType: UITableViewCell.AccessoryType = manager.changeState(at: indexPath.row) ? .checkmark : .none

当isFiltering为true时,indexPath.row对应的是filteredTasks里的位置,而不是manager.tasks(原始数组)的真实位置。比如你筛选后第三个元素是原始数组的第五个,你点击后却修改了原始数组的第三个元素,取消搜索自然就看到错误的结果啦。

修复方案

我们需要先拿到筛选后点击的Task对象,再找到它在原始数组里的真实索引,然后再去修改状态。具体修改你的didSelectRowAt方法:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
    
    // 确定要修改的原始数组索引
    let targetIndex: Int
    if isFiltering {
        // 先获取筛选后的当前任务
        guard let currentTask = filteredTasks?[indexPath.row] else { return }
        // 找到它在原始数组中的真实位置
        // 这里假设你的Task实现了Equatable协议,如果没有,用唯一ID匹配
        guard let index = manager.tasks.firstIndex(where: { $0 == currentTask }) else { return }
        targetIndex = index
    } else {
        // 非筛选状态直接用当前索引
        targetIndex = indexPath.row
    }
    
    // 修改状态并更新cell
    let accessoryType: UITableViewCell.AccessoryType = manager.changeState(at: targetIndex) ? .checkmark : .none
    tableView.cellForRow(at: indexPath)?.accessoryType = accessoryType
}

额外说明

如果你的Task类没有实现Equatable协议,记得用唯一标识来匹配(比如每个任务的taskId),替换上面的匹配逻辑:

guard let index = manager.tasks.firstIndex(where: { $0.taskId == currentTask.taskId }) else { return }

这样就能确保精准找到原始数组中对应的任务,不会再出现索引错位的问题啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 20:27:28