如何为NSStatusBarButton注册点击事件?点击按钮未触发回调
首先得点明核心原因:当你给NSStatusItem设置了menu属性后,系统会自动接管状态栏按钮的点击逻辑——点击按钮时直接弹出菜单,不会触发你绑定的按钮点击事件(也就是你的statusBarButtonClicked函数不会被调用)。
根据你“点击按钮时更新菜单内容”的需求,这里有两种靠谱的解决方案:
方案一:手动管理菜单弹出,绑定按钮点击事件
这种方式是移除系统默认的菜单绑定,自己处理按钮点击和菜单弹出,这样就能触发你的点击事件了:
@IBOutlet weak var statusMenu: NSMenu! let log = SwiftyBeaver.self let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) override func awakeFromNib() { // 不要设置statusItem.menu,我们自己处理菜单弹出 if let button = statusItem.button { button.image = NSImage(named: "你的状态栏图标") // 替换成你的图标 button.action = #selector(statusBarButtonClicked(_:)) button.target = self button.sendAction(on: [.leftMouseUp]) // 指定触发点击事件的鼠标操作 } } @objc func statusBarButtonClicked(_ sender: NSStatusBarButton) { // 先更新菜单内容 updateMenuContent() // 手动弹出菜单 statusMenu.popUp( positioning: nil, at: NSPoint(x: sender.bounds.minX, y: sender.bounds.maxY), in: sender ) } private func updateMenuContent() { // 写你的菜单更新逻辑,比如清除旧项、添加新内容 statusMenu.removeAllItems() statusMenu.addItem(NSMenuItem(title: "更新后的菜单选项", action: nil, keyEquivalent: "")) // ... 其他菜单更新操作 }
方案二:监听菜单即将打开的通知(更贴合原生交互)
如果你不想改变系统默认的菜单弹出逻辑,可以监听NSMenu.willOpenNotification通知——菜单即将被打开时(也就是用户点击状态栏按钮的时机),自动更新菜单内容:
@IBOutlet weak var statusMenu: NSMenu! let log = SwiftyBeaver.self let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) override func awakeFromNib() { statusItem.menu = statusMenu // 添加菜单即将打开的通知监听 NotificationCenter.default.addObserver( self, selector: #selector(menuWillOpen(_:)), name: NSMenu.willOpenNotification, object: statusMenu ) if let button = statusItem.button { button.image = NSImage(named: "你的状态栏图标") } } @objc func menuWillOpen(_ notification: Notification) { // 菜单即将弹出,更新内容 updateMenuContent() } private func updateMenuContent() { // 你的菜单更新逻辑 statusMenu.removeAllItems() statusMenu.addItem(NSMenuItem(title: "实时更新的菜单", action: nil, keyEquivalent: "")) // ... } // 记得在销毁时移除监听,避免内存泄漏 deinit { NotificationCenter.default.removeObserver(self) }
关键注意点
- 所有被Selector调用的方法必须标记
@objc,因为OC运行时需要识别这些方法 - 方案二更符合macOS原生交互逻辑,用户体验更自然,推荐优先使用
- 如果你的菜单内容需要实时刷新,方案二的时机刚好匹配用户点击按钮的操作
内容的提问来源于stack exchange,提问作者FoundNil
相关产品推荐
相关产品推荐

