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

打开/点击NSStatusItem时刷新NSMenuItem状态的实现方法

问题原因

你当前的代码仅在创建菜单项时给state赋了一次初始值,之后sHandler状态变更时没有同步修改菜单项的state属性——NSMenuItem不会自动监听外部对象的状态变化,必须手动同步属性值才会更新勾选标记。

解决方案

首先做前置修改:把enableDisableMenuItem从createStatusBarItem()的局部变量改成AppDelegate的实例属性,否则后续方法里无法拿到这个菜单项实例做修改:

// AppDelegate 中新增属性
private weak var enableDisableMenuItem: NSMenuItem?

修改createStatusBarItem()里的菜单项初始化逻辑,把实例存到属性中:

// 替换原来的 let enableDisableMenuItem = NSMenuItem(...) 代码
let enableItem = NSMenuItem(title: "Enabled", action: #selector(toggleAdvancedMouseHandlingObjc), keyEquivalent: "e")
enableItem.state = sHandler.isAdvancedMouseHandlingEnabled() ? .on : .off
sBarMenu.addItem(enableItem)
self.enableDisableMenuItem = enableItem

根据业务场景选下面任意一种同步方式即可:

  • 方案1:点击切换时直接同步(最简单)
    如果sHandler的高级鼠标处理状态只会通过点击这个菜单项触发切换,直接在切换方法里改完状态后同步菜单项属性即可:
@objc func toggleAdvancedMouseHandlingObjc() {
    if sHandler.isAdvancedMouseHandlingEnabled() {
        sHandler.disableAdvancedMouseHandling()
    } else {
        sHandler.enableAdvancedMouseHandling()
    }
    // 同步菜单项勾选状态
    enableDisableMenuItem?.state = sHandler.isAdvancedMouseHandlingEnabled() ? .on : .off
}
  • 方案2:菜单打开时同步(最稳妥,推荐)
    如果状态可能被其他路径修改(比如设置页开关、全局快捷键、其他业务逻辑触发启停),用NSMenu的代理方法做同步最省心,不需要在所有修改状态的地方加更新逻辑,只要用户点开菜单就一定能拿到最新状态:
  1. 在createStatusBarItem()里给菜单设置代理:
    // sBarMenu 初始化后添加这行
    sBarMenu.delegate = self
    
  2. 实现代理方法,在菜单即将打开时同步状态:
    extension AppDelegate: NSMenuDelegate {
        func menuWillOpen(_ menu: NSMenu) {
            enableDisableMenuItem?.state = sHandler.isAdvancedMouseHandlingEnabled() ? .on : .off
        }
    }
    
  • 方案3:状态变更监听(适合多UI联动场景)
    如果你需要在菜单不打开时也同步状态(比如要根据开关状态改状态栏图标样式、同步其他UI元素),可以给sHandler的状态属性加KVO观察,或者用Combine/NotificationCenter在状态变化时发通知,收到回调后统一更新所有关联UI的状态,包括菜单项的state属性。

注意:不需要调用任何强制刷新UI的方法,NSMenuItem的state属性是赋值即生效的,你看到勾选不更新的核心原因是属性值没有同步,不是视图没有重绘。

内容的提问来源于stack exchange,提问作者Christian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 21:36:38