解决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
相关产品推荐
相关产品推荐

