如何识别macOS中MenuBarExtra是否被系统隐藏并监听状态变化
在AppKit中,菜单栏额外项对应NSStatusItem类。要判断它是否被系统隐藏到overflow菜单(即右侧的更多选项菜单),以及监听状态变化,可以通过以下方式实现:
一、判断当前是否被系统隐藏
系统会将超出菜单栏空间的NSStatusItem移入overflow菜单,此时可以通过NSStatusBar的visibleItems属性判断你的项是否在当前显示的列表中:
Swift 示例
let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) // 判断是否显示在菜单栏中 let isVisibleInMenuBar = NSStatusBar.system.visibleItems.contains(statusItem)
Objective-C 示例
NSStatusItem *statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSStatusItemVariableLength]; BOOL isVisibleInMenuBar = [[[NSStatusBar systemStatusBar] visibleItems] containsObject:statusItem];
二、监听隐藏/显示状态变化
AppKit没有提供直接针对NSStatusItem隐藏状态的通知,但可以通过监听其关联按钮的窗口可见性变化来实现——当系统将NSStatusItem移入overflow菜单时,其按钮所在的窗口会被隐藏;移回菜单栏时窗口会重新显示。
Swift 示例
// 假设已初始化statusItem if let buttonWindow = statusItem.button?.window { // 监听窗口变为可见(即项回到菜单栏) NotificationCenter.default.addObserver(forName: NSWindow.didBecomeVisibleNotification, object: buttonWindow, queue: .main) { [weak self] _ in // 在这里处理显示逻辑 print("菜单栏项已显示") } // 监听窗口变为隐藏(即项被移入overflow菜单) NotificationCenter.default.addObserver(forName: NSWindow.didResignVisibleNotification, object: buttonWindow, queue: .main) { [weak self] _ in // 在这里处理隐藏逻辑 print("菜单栏项已被隐藏到overflow菜单") } } // 注意:在合适的时机(如deinit)移除观察者 deinit { NotificationCenter.default.removeObserver(self) }
Objective-C 示例
// 假设已初始化statusItem NSWindow *buttonWindow = statusItem.button.window; if (buttonWindow) { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusItemDidShow:) name:NSWindowDidBecomeVisibleNotification object:buttonWindow]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusItemDidHide:) name:NSWindowDidResignVisibleNotification object:buttonWindow]; } // 处理显示事件的方法 - (void)statusItemDidShow:(NSNotification *)note { NSLog(@"菜单栏项已显示"); } // 处理隐藏事件的方法 - (void)statusItemDidHide:(NSNotification *)note { NSLog(@"菜单栏项已被隐藏到overflow菜单"); } // 在dealloc中移除观察者 - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; }
注意事项
- 若你的
NSStatusItem未设置按钮(button为nil),则无法通过窗口监听的方式判断状态,这种情况下建议始终为NSStatusItem设置按钮。 - 监听时需注意避免循环引用,Swift中使用
weak self,Objective-C中确保在对象销毁时移除观察者。
内容的提问来源于stack exchange,提问作者Vipul Gupta
相关产品推荐
相关产品推荐

