点击UICollectionView切换图片位置错误、多选异常问题排查
问题根因
- 单选逻辑缺失:点击按钮时仅修改了当前点击项的选中状态,未将之前选中的项的
isImageSelected重置为false,导致多个项同时被标记为选中 - UI状态与数据源不同步:你直接在点击方法中修改按钮的图片,但是在
cellForItemAt复用cell时仅设置了logoButton.isSelected,没有同步设置按钮图片,cell复用后就会出现图片显示错乱 - 重复添加点击事件:每次cell复用都会给按钮添加一次点击回调,多次复用后点击按钮会触发多次逻辑,进一步导致状态混乱
修复方案
推荐优先使用UICollectionView自带的选中回调实现,避免tag、重复添加事件等问题,修改后代码如下:
1. 优化cell复用逻辑
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let teamSelection = self.teamCollectionView.dequeueReusableCell(withReuseIdentifier: "teamCell", for: indexPath) as! TeamSelectionCollectionViewCell let row = teamSelectionList[indexPath.row] teamSelection.logoImage.image = UIImage(named: row.logoImage) // 所有UI状态完全从数据源读取,不要在其他地方直接修改UI控件状态 if row.isImageSelected { teamSelection.logoButton.setImage(UIImage(named: "ic_radio_selected"), for: .normal) } else { teamSelection.logoButton.setImage(UIImage(named: "ic_radio_normal"), for: .normal) } // 禁用按钮单独响应,统一交给cell选中事件处理 teamSelection.logoButton.isUserInteractionEnabled = false teamSelection.seperatorView.isHidden = indexPath.row == 2 || indexPath.row == self.teamSelectionList.count - 1 return teamSelection }
2. 新增collectionView选中回调,替换原有的按钮点击方法
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { // 先重置上一个选中项的状态 if currentIndex != indexPath.row { teamSelectionList[currentIndex].isImageSelected = false } // 切换当前点击项的选中状态 teamSelectionList[indexPath.row].isImageSelected.toggle() // 更新当前选中下标 currentIndex = indexPath.row // 刷新列表同步UI teamCollectionView.reloadData() }
如果你需要保留按钮点击的实现,做如下修改即可:
- 在
cellForItemAt添加target前先移除旧的回调,避免重复触发:
teamSelection.logoButton.removeTarget(self, action: #selector(logoButtonTapped), for: .touchUpInside) teamSelection.logoButton.tag = indexPath.row teamSelection.logoButton.addTarget(self, action: #selector(logoButtonTapped), for: .touchUpInside)
- 修改按钮点击逻辑:
@objc func logoButtonTapped(sender: UIButton){ let tapIndex = sender.tag // 重置上一个选中项状态 if currentIndex != tapIndex { teamSelectionList[currentIndex].isImageSelected = false } // 切换当前项选中状态 teamSelectionList[tapIndex].isImageSelected.toggle() currentIndex = tapIndex teamCollectionView.reloadData() }
内容的提问来源于stack exchange,提问作者iFateh
相关产品推荐
相关产品推荐

