iOS15更新后UITableViewCell内按钮无法正常点击的问题及解决
iOS 15 下UITableViewCell内置按钮点击异常解决
问题背景
存在一个数据频繁更新的UITableView,其自定义Cell内部集成了交互按钮,该按钮在iOS 11 ~ iOS 14系统上运行完全正常,升级到iOS 15后出现三类交互异常。
异常表现
- 单元格处于数据更新状态时按钮无法响应触摸操作,点击无反馈
- 正常状态下也需要多次点击才有可能触发对应的点击事件
- 事件触发时偶现上下文错位,例如点击第1个单元格的按钮,响应方法收到的sender却属于第2个单元格
原实现代码
原有按钮事件绑定逻辑如下:
cell.contentView.isUserInteractionEnabled = true cell.button.addTarget(self, action: #selector(self.doSomething(sender:)), for: .touchUpInside)
根因说明
iOS 15对UITableView的重用和刷新机制做了调整,频繁调用全局reloadData方法时,会触发可见Cell的全量重建回收,过程中会临时阻断交互响应,同时如果在cellForRowAt中重复添加target,会导致事件绑定混乱,最终出现点击无响应、触发错位等问题。
最优解决方案
使用iOS 15新增的reconfigureRows(at:)方法替代全局reloadData即可解决问题,该方法仅更新Cell的内容数据,不会触发Cell的重建与重用流程,也不会打断正在进行的触摸交互,适配代码如下:
let indexPaths = tableView.indexPathsForVisibleRows! if !indexPaths.isEmpty { tableView.reconfigureRows(at: indexPaths) }
低版本兼容方案
如果需要兼容iOS 15以下系统,可以通过以下优化缓解问题:
- 将按钮的
addTarget逻辑移到Cell的初始化方法中,避免每次Cell重用时重复绑定事件,通过闭包或者代理将点击事件回传到业务层处理 - 替换全局
reloadData为局部刷新,仅更新数据有变更的行,调用reloadRows(at:with:)方法 - 给不同类型的Cell设置唯一的重用标识,避免不同类型Cell重用导致的逻辑混乱
内容的提问来源于stack exchange,提问作者vyppN
相关产品推荐
相关产品推荐

