iOS Swift中TableViewCell自定义按钮单选功能异常排查
问题排查与修复方案
问题根源
- 单选逻辑选型错误:用数组
selectedRows处理单选需求冗余且容易引发逻辑混乱,单选场景只需记录单个选中行号即可。 - UI更新逻辑错误:闭包中直接操作当前
cell的按钮状态,未考虑TableView的复用机制,导致已选中的旧cell无法同步更新状态。 - 数组操作异常:遍历
selectedRows时直接删除元素,会触发数组遍历过程中修改的越界问题,同时重复的条件判断导致UI状态混乱。 - 未处理取消选中场景:原代码仅处理“未选中时添加”的情况,缺失重复点击取消选中的逻辑。
修复后的代码实现
1. 替换选中状态存储变量
将原数组selectedRows替换为单个可选整数,简化单选状态管理:
// 记录当前选中的行号,nil表示无选中项 var selectedRow: Int?
2. 修正cellForRowAt方法
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "你的Cell标识符", for: indexPath) as! YourTableViewCell // 绑定行号到按钮tag cell.buttonRadio.tag = indexPath.row // 初始化时根据选中状态设置按钮图标(适配cell复用) let isCurrentSelected = selectedRow == indexPath.row cell.buttonRadio.setImage(UIImage(named: isCurrentSelected ? "radioSelected" : "radioUnselected"), for: .normal) // 按钮点击事件处理 cell.selectCategory = { [weak self] tappedRow in guard let self = self else { return } // 单选逻辑:点击已选中行则取消,否则切换选中当前行 if self.selectedRow == tappedRow { self.selectedRow = nil } else { self.selectedRow = tappedRow } // 更新底部按钮状态 let hasSelectedItem = self.selectedRow != nil self.buttonLink.isUserInteractionEnabled = hasSelectedItem self.buttonLink.backgroundColor = hasSelectedItem ? UIColor(hex: "#453073") : UIColor(hex: "#A297B9") // 刷新受影响的行,确保所有cell状态同步 if let previousRow = self.selectedRow { tableView.reloadRows(at: [IndexPath(row: previousRow, section: 0)], with: .automatic) } tableView.reloadRows(at: [IndexPath(row: tappedRow, section: 0)], with: .automatic) } return cell }
3. TableViewCell代码保持不变
你的Cell代码无需修改,继续使用:
var selectCategory: ((Int) -> Void)? @IBAction func didTapSelected(_ sender: UIButton) { selectCategory?(sender.tag) }
关键修复点说明
- 用单个变量替代数组,彻底简化单选逻辑,避免数组操作的潜在bug。
- 在
cellForRowAt中直接根据选中状态初始化按钮图标,适配TableView的cell复用机制,确保每次cell复用都能显示正确状态。 - 通过
reloadRows刷新受影响的行,解决了原代码中仅更新当前cell、旧选中cell状态不更新的问题。 - 使用
[weak self]避免循环引用,防止内存泄漏。 - 增加了重复点击取消选中的逻辑(若不需要该功能,可直接将逻辑改为
self.selectedRow = tappedRow)。
内容的提问来源于stack exchange,提问作者Shaikh
相关产品推荐
相关产品推荐

