You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS中UIBarButtonItem菜单弹出时如何获取对应的触发事件?

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 14:54:01