UICollectionViewCell中Radio Button点击后无法取消其他选中项问题
问题根因
你当前的实现默认是多选逻辑,使用Set存储所有被选中的下标,新增选中项时不会清空旧的选中记录,因此会出现多个按钮同时选中的问题。此外你定义的TeamSelected结构体中的isImageSelected字段完全没有被使用,所有选中状态都通过外部的selection变量判断,属于冗余字段,容易引发状态不一致问题。
修复方案
对核心逻辑做如下修改即可实现单选效果:
- 替换选中状态存储变量
将原有的Set类型的选中存储变量改为可选Int类型,单选场景下最多仅会有一个选中项,用可选类型更合适:
// 替换原有的 var selection = Set<Int>() var selectedIndex: Int?
- 修改cellForItemAt中的选中判断逻辑
将原有的Set包含判断改为相等判断:
// 替换原有的 let isImageSelected = selection.contains(index) let isImageSelected = selectedIndex == index
- 修改按钮点击响应逻辑
点击新的选项时直接覆盖选中下标即可:
@objc func logoButtonTapped(sender: UIButton){ let index = sender.tag // 如果需要支持点击已选中项取消选中,保留if分支,不需要则直接赋值selectedIndex = index即可 if selectedIndex == index { selectedIndex = nil } else { selectedIndex = index } self.teamCollectionView.reloadData() }
优化建议
- 避免重复绑定点击事件:UICollectionViewCell存在复用机制,你每次调用
cellForItemAt都会给按钮添加一次target,多次复用后同一个按钮会绑定多个响应方法,点击时会触发多次回调。建议将addTarget逻辑移到TeamSelectionCollectionViewCell的初始化方法中,通过闭包或者代理将点击事件传递到外层处理,比使用tag存储下标更安全,避免列表增删元素后tag不准的问题。 - 优化刷新性能:不需要每次点击都全量刷新整个CollectionView,仅需要刷新上一次选中的和当前选中的两个cell即可,性能更好:
@objc func logoButtonTapped(sender: UIButton){ let index = sender.tag // 记录之前的选中下标 let oldIndex = selectedIndex if selectedIndex == index { selectedIndex = nil } else { selectedIndex = index } // 仅刷新需要更新的cell var reloadPaths = [IndexPath(row: index, section: 0)] if let old = oldIndex, old != index { reloadPaths.append(IndexPath(row: old, section: 0)) } self.teamCollectionView.reloadItems(at: reloadPaths) }
内容的提问来源于stack exchange,提问作者iFateh
相关产品推荐
相关产品推荐

