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

解决UISearchController激活/关闭时UITableViewCell选中状态丢失问题

修复UITableView搜索时勾选状态丢失的问题

问题根源在于你依赖UITableView的选中状态管理勾选,而搜索时tableView会重新加载数据,原有的选中indexPath会失效,且tableView的选中状态没有和数据模型绑定,导致状态丢失。正确的做法是把选中状态存在Part模型里,让UI显示完全依赖模型数据。

以下是具体修改步骤:

1. 修改Part模型,添加选中状态属性

将Part从结构体改为类(引用类型),确保搜索结果中的对象和原数组对象是同一个,修改状态时能同步到原数组:

class Part: Equatable {
    var title: String?
    var location: String?
    var isSelected: Bool = false // 新增选中状态标记
    
    init(title: String?, location: String?) {
        self.title = title
        self.location = location
    }
    
    // 实现Equatable协议,用于匹配原数组中的对象
    static func == (lhs: Part, rhs: Part) -> Bool {
        return lhs.title == rhs.title && lhs.location == rhs.location
    }
}

注意:更新InspectorPartsList.getDamageUnrelatedParts()方法,使其返回[Part]类型的数组,初始化每个Part对象时isSelected默认设为false。

2. 调整Cell的配置逻辑

在cellForRowAt中,根据模型的isSelected属性直接设置Cell的选中状态和勾选标记,不再依赖tableView的选中状态:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let inspectorCell = tableView.dequeueReusableCell(withIdentifier: "inspectorCell", for: indexPath) as! CheckableTableViewCell
    
    var content = inspectorCell.defaultContentConfiguration()
    let part: Part
    if isFiltering {
        part = filteredParts[indexPath.row]
    } else {
        part = parts[indexPath.row]
    }
    content.text = part.title
    content.secondaryText = part.location
    inspectorCell.contentConfiguration = content
    
    // 直接根据模型状态设置Cell显示
    inspectorCell.isSelected = part.isSelected
    inspectorCell.accessoryType = part.isSelected ? .checkmark : .none
    
    return inspectorCell
}

3. 修改选中Cell的逻辑,更新模型状态

点击Cell时,切换对应Part对象的isSelected属性,然后刷新Cell:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let targetPart: Part
    if isFiltering {
        targetPart = filteredParts[indexPath.row]
        // 找到原数组中对应的对象并更新状态
        if let originalIndex = parts.firstIndex(of: targetPart) {
            parts[originalIndex].isSelected.toggle()
        }
    } else {
        targetPart = parts[indexPath.row]
        targetPart.isSelected.toggle()
    }
    // 刷新当前Cell,同步显示状态
    tableView.reloadRows(at: [indexPath], with: .automatic)
}

4. 调整完成按钮的逻辑,直接从模型获取选中项

不再依赖tableView的选中indexPath,直接从原数组中筛选isSelected为true的对象:

@objc func addBtnTapped() {
    print("Done tapped")
    // 从模型中筛选所有选中的零件
    let selectedParts = parts.filter { $0.isSelected }
    
    // 更新InspectionData模型
    InspectionData.sharedInstance.partsData?.append(contentsOf: selectedParts)
    
    // 通知刷新外部表格
    updateInspectionTableView()
    
    // 关闭弹窗
    SPStorkController.dismissWithConfirmation(controller: self, completion: nil)
}

5. 可选:调整CheckableTableViewCell

注释掉Cell中原来的setSelected方法,避免和我们手动设置的状态冲突:

class CheckableTableViewCell: UITableViewCell {
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.selectionStyle = .none
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
    
    // 注释掉原有逻辑,避免干扰手动设置的状态
    /*
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        self.accessoryType = selected ? .checkmark : .none
    }
    */
}

这样修改后,无论搜索状态如何切换,选中状态都会保存在模型中,不会丢失,完全符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 22:15:36