【问题标题】:How to update NSMenu while it's open?如何在打开时更新 NSMenu?
【发布时间】:2026-01-13 11:55:01
【问题描述】:

我有一个动态添加 NSMenuItems 的 NSMenu。 NSMenu 在保持打开状态时未正确刷新。我在NSEventTrackingRunLoopModes调用NSMenu更新方法。

我已经实现了以下方法来更新 NSMenu。

- (void)menuNeedsUpdate:(NSMenu *)menu {
for (NSInteger index = 0; index < count; index++)
    [self menu:menu updateItem:[menu itemAtIndex:index] 
                       atIndex:index 
                  shouldCancel:NO];
}

- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel`

- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu

【问题讨论】:

  • 我也有类似的问题。我想在打开时更新 NSMenu,具体取决于用户是否按下选项键。当产品菜单打开并按下选项键时,我需要 Xcode 的行为。这可以通过内置的 NSMenu 方法来完成吗?

标签: objective-c cocoa nsmenuitem nsmenu nsstatusbar


【解决方案1】:

更新NSEventTrackingRunLoopMode 中的菜单项解决了这个问题。

【讨论】:

    【解决方案2】:

    我在计时器中动态填充菜单项,而 NSMenu 在打开时没有更新。

    确保在相应的运行模式下触发计时器:

    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    

    您现在可能只能在 NSDefaultRunLoopMode 上触发它。

    【讨论】:

    • 我尝试过使用 NSRunLoopCommonModes,但在打开时仍然出现菜单刷新问题
    【解决方案3】:

    你遗漏了一堆代码。但是,您不应该拨打-menu:updateItem:atIndex:shouldCancel:。这是你应该实现的方法,框架应该调用它。

    另外,通常你只需要实现-menuNeedsUpdate: 或者这两个-numberOfItemsInMenu:-menu:updateItem:atIndex:shouldCancel:。实现所有三个没有多大意义。如果您可以立即构建菜单,则可以实施前者。如果构建菜单需要一些时间,则实现后两者。

    最后,所有这些方法都被记录为“当菜单即将显示时”。在菜单打开时他们没有被重复调用,我并不感到非常惊讶。

    如果您知道菜单需要更新,您可以尝试调用-[NSMenu update]。这可能会引发它调用您的委托方法。我很确定您也可以只调用 NSMenuNSMenuItem 上的方法来修改菜单,而无需等待调用您的委托。

    【讨论】:

    • [NSMenu update] 不调用任何委托方法。我在计时器中动态填充菜单项,并且 NSMenu 在打开时没有更新。
    • 即使您调用 -[NSMenu addItem:]-[NSMenuItem setTitle:] 之类的东西来响应您的计时器,它也不会更新?我确定我看到菜单在打开时会更新,所以这是可能的。
    • @KenThomases 第一方操作系统时钟可以做到这一点(如果显示秒数会更明显)。
    最近更新 更多