Swift3 嵌套UITableView didSelectRowAt触发后多Cell同索引行选中问题

问题原因
- 你当前用了全局共享的
isSelectedIndex、isIndexSelected两个变量存储选中状态,所有父Cell内嵌的子UITableView都复用这组状态变量,自然会出现相同索引行同步选中的问题 - 子UITableView选中后你调用的是父tableView
tblViewAudit的全量重载,状态没有和对应的父Cell、子选项绑定,也会导致选中状态错乱
解决步骤
1. 改造选中状态存储结构
不要用全局的单个变量存选中,改为用字典存储每个父Cell对应选中的子选项索引,结构示例:
// key为父Cell的索引(即父tableView的indexPath.row),value为该父Cell下选中的子选项行索引,未选中则不存储对应key var selectedIndexMap: [Int: Int] = [:]
2. 给子UITableView绑定对应父Cell的索引
在父Cell(AuditQuestionsTblCell)定义时,增加parentIndex属性存储当前父Cell在父tableView中的位置,赋值父Cell时将索引同步给子tableView的tag:
// 父tableView的cellForRowAt中修改代码 cell?.tblViewAnswer.tag = indexPath.row // 子tableView的tag等于父cell的索引 cell?.parentIndex = indexPath.row
3. 替换子Cell的选中状态判断逻辑
子tableView渲染Cell时,先取当前子tableView对应的父索引,从selectedIndexMap中查询该父Cell下的选中行,再判断当前行的选中状态:
// 替换原有子cell配置中的选中判断代码 let parentIndex = tableView.tag let currentSelectedIndex = selectedIndexMap[parentIndex] ?? -1 if currentSelectedIndex == indexPath.row { cell?.viewOption.backgroundColor = UIColor.blue } else { cell?.viewOption.backgroundColor = UIColor.lightGray }
4. 改造选中事件逻辑
选中子Cell时仅重载当前对应的子tableView,无需全量重载父tableView,避免状态错乱同时提升性能:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { guard tableView.tag != 101 else { return } // 过滤父tableView的选中事件 let parentIndex = tableView.tag // 切换选中状态:已选中则取消,未选中则标记当前行为选中 if selectedIndexMap[parentIndex] == indexPath.row { selectedIndexMap.removeValue(forKey: parentIndex) } else { selectedIndexMap[parentIndex] = indexPath.row } // 仅重载当前子tableView tableView.reloadData() }
5. 额外优化点
- 如果不同父Cell的子选项列表不同,不要全局共用
arrOptionList数据源,需将子选项列表存储到父数据源的对应字段中,渲染时根据父索引取对应子选项数组 - 子cell上的按钮点击事件
methodOptionSelection也需要按照上述逻辑调整,不要依赖全局变量判断状态
内容的提问来源于stack exchange,提问作者Sunil
相关产品推荐
相关产品推荐

