UIContextMenuConfiguration上下文菜单弹出多个重复项问题
UITableView长按上下文菜单重复项问题修复
问题场景
按section分组展示item的UITableView,实现长按弹出上下文菜单功能,核心初始实现代码如下:
func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? { return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { _ in UIMenu(title: "", children: [ UIAction(title: R.string.localizable.delete(), image: UIImage(systemName: "trash"), attributes: .destructive) { _ in // 删除业务逻辑 ... } ]) } }
异常表现
弹出上下文菜单时出现多个重复操作项,项之间存在自动切换动画,预期仅展示单个对应操作项;异常触发不稳定,有时会在两个重复项之间播放切换动画,有时又能正常仅展示单个操作项。
异常表现截图:

问题原因
初始化UIContextMenuConfiguration时将identifier参数传入了nil,系统无法唯一标识当前触发菜单的cell位置,在分组TableView的cell复用逻辑下,会错误匹配其他位置的菜单配置,导致重复渲染、出现切换动画的异常。
修复方案
给UIContextMenuConfiguration传入全局唯一的identifier,直接使用触发位置的indexPath作为identifier即可(NSIndexPath实现了NSCopying协议,符合identifier参数类型要求)。
修复后代码:
func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? { // 传入indexPath作为唯一标识,禁止传nil return UIContextMenuConfiguration(identifier: indexPath as NSCopying, previewProvider: nil) { _ in UIMenu(title: "", children: [ UIAction(title: R.string.localizable.delete(), image: UIImage(systemName: "trash"), attributes: .destructive) { _ in // 原有删除业务逻辑保持不变 ... } ]) } }
额外注意
- 所有使用
UIContextMenuConfiguration的场景(包括UITableView、UICollectionView)都不要给identifier传nil,尤其是存在cell复用、分组/多列表结构的页面,系统依赖唯一identifier匹配对应触发位置的菜单配置,避免复用错误 - 如果页面存在跨位置indexPath重复的情况,可以传入对应业务数据的唯一ID作为identifier,保证全局唯一即可
内容的提问来源于stack exchange,提问作者ArisRS
相关产品推荐
相关产品推荐

