强制更新 Cocoa 应用程序主菜单的 NSMenu(嵌套子菜单)

Unc*_*MiF 2 cocoa nsmenu appkit

    \n
  1. 我插入了一些子菜单作为主菜单的窗口项子菜单
  2. \n
  3. 我有一个从 NSObject 继承的对象实例(假设其类名为 MenuController),并支持 NSMenuDelegate 方法中的 2 个:\n\xe2\x80\x93 numberOfItemsInMenu:\n\xe2\x80\x93 menu:updateItem :atIndex:应该取消:
  4. \n
  5. 该实例作为蓝色对象添加到 NIB 中以便在运行时唤醒
  6. \n
  7. 将步骤 2-3 中的对象配置为子菜单的委托(步骤 1)
  8. \n
\n\n

现在,我可以在运行时提供子菜单内容。

\n\n

接下来,我执行以下操作:我可以添加新项目或从数组(包含菜单标题的 MenuController 内部)中删除旧项目,该数组通过协议和委托映射到真实的子菜单。\n一切都很好。\n除了一件事:我喜欢分配快捷方式到我的动态菜单项。\nCMD-1、CMD-2、CMD-3 等

\n\n

窗口 / MySubmenu / MyItem1 CMD-1, MyItem2 CMD-2, ...

\n\n

因此,为了调用某些项目,我不想去 Window / MySubmenu / MyItem 通过鼠标单击它,我只想按一个快捷键,例如 CMD-3 来调用该项目。

\n\n

好的,定期它会按预期工作。但是,一般来说,我无法通知主菜单有关嵌套子菜单的更改,除非打开 Window / MySubmenu 重新加载其内容。\n重现该问题的一种稳定方法 - 只需尝试删除某些项目并按分配的旧快捷键即可对此,在您创建新项目作为已删除的替换后 - 宾果 - 在导航到 Window / MySubmenu 查看当前子菜单内容之前,快捷方式将不起作用。

\n\n

我不知道如何强制主菜单重建其子菜单...\n我尝试过:[[NSApp mainMenu] update] 和使用 NSNotificationCenter 发送 NSMenuDidAddItemNotification、NSMenuDidRemoveItemNotification、NSMenuDidChangeItemNotification 的游戏

\n\n

我尝试出口到我的子菜单并显式调用更新方法 - 没有办法...\n有时 AppKit 调用我的委托方法 - 我发现,有时它不想调用任何东西。看起来像是一个随机策略。

\n\n

如何确保在“某些调用”之后我的子菜单在内部数组修改后将处于实际状态?

\n

Unc*_*MiF 5

要实现 1:1 映射,请在委托中实现以下 3 个方法:

- (BOOL)menu:(NSMenu *)menu
updateItem:(NSMenuItem *)item 
atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel
Run Code Online (Sandbox Code Playgroud)

- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu
Run Code Online (Sandbox Code Playgroud)

- (void)menuNeedsUpdate:(NSMenu *)menu
{
    if (!attachedMenu)
        attachedMenu = menu;
    if (!menu)
        menu = attachedMenu;
    NSInteger count = [self numberOfItemsInMenu:menu];
    while ([menu numberOfItems] < count)
        [menu insertItem:[[NSMenuItem new] autorelease] atIndex:0];
    while ([menu numberOfItems] > count)
        [menu removeItemAtIndex:0];
    for (NSInteger index = 0; index < count; index++)
        [self menu:menu updateItem:[menu itemAtIndex:index] atIndex:index shouldCancel:NO];
}
Run Code Online (Sandbox Code Playgroud)

AttachedMenu - 是 NSMenu* 类型的内部变量

接下来,当您想强制刷新子菜单时,随时 - 只需调用

[self menuNeedsUpdate:nil];
Run Code Online (Sandbox Code Playgroud)