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

如何识别macOS中MenuBarExtra是否被系统隐藏并监听状态变化

如何检测并监听NSStatusItem(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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 16:23:10