iOS中UIBarButtonItem菜单弹出时如何获取对应的触发事件?
我们都知道iOS 14引入了轻点UIBarButtonItem弹出菜单的能力,基础实现代码如下:
let act = UIAction(title: "Howdy") { act in print("Howdy") } let menu = UIMenu(title: "", children: [act]) self.bbi.menu = menu // self.bbi is the bar button item
目前基础功能可正常运行,但我在按钮被点击、菜单显示时还需要执行暂停游戏计时器等额外操作,因此需要获取菜单正在弹出的事件通知。
我不希望点击事件和菜单弹出行为分离:如果给按钮绑定target-action,菜单就只能通过长按触发,不符合我轻点即弹出菜单同时收到事件的需求。
这应该是个常见问题,请问大家通常是如何解决的?
常用解决方案有两种,均适配iOS14+,无需绑定target-action:
方案1:使用primaryAction属性(最简单推荐)
iOS14后UIBarButtonItem新增的primaryAction会在轻点按钮时优先触发,同时不会影响菜单的正常弹出,实现代码如下:
// 定义轻点按钮时需要执行的额外操作 let triggerAction = UIAction(title: "") { [weak self] _ in guard let self = self else { return } // 示例:暂停游戏计时器 self.gameTimer.pause() } // 原有菜单逻辑保持不变 let menuAction = UIAction(title: "Howdy") { _ in print("Howdy") } let menu = UIMenu(title: "", children: [menuAction]) // 同时赋值两个属性即可 self.bbi.primaryAction = triggerAction self.bbi.menu = menu
方案2:通过UIDeferredMenuElement拦截菜单加载时机
如果需要仅在菜单实际弹出时才执行操作(避免点击后菜单未弹出却误触发逻辑的极端情况),可以用延迟菜单元素包裹原有菜单项,在加载回调中执行自定义逻辑:
let deferredElement = UIDeferredMenuElement { [weak self] completion in guard let self = self else { completion([]) return } // 菜单即将显示,执行自定义操作 self.gameTimer.pause() // 构建原有菜单项返回 let menuAction = UIAction(title: "Howdy") { _ in print("Howdy") } completion([menuAction]) } let menu = UIMenu(title: "", children: [deferredElement]) self.bbi.menu = menu
注意:不要同时给UIBarButtonItem设置
target-action和menu,否则会触发「轻点执行action、长按才弹出菜单」的默认行为,不符合需求。
内容的提问来源于stack exchange,提问作者matt
相关产品推荐
相关产品推荐

