Cocoa应用程序主菜单的强制NSMenu(嵌套子菜单)更新 我有一些子菜单作为主菜单的窗口项子菜单插入 我有一个从NSObject继承的对象实例(假设其类名为MenuController),并支持从NSMenuDelegate方法继承的2: –NumberOfItems菜单: –菜单:更新项:索引:应取消: 此实例作为蓝色对象添加到NIB中,以便在运行时唤醒 步骤2-3中的对象配置为子菜单的委托(步骤1)

Cocoa应用程序主菜单的强制NSMenu(嵌套子菜单)更新 我有一些子菜单作为主菜单的窗口项子菜单插入 我有一个从NSObject继承的对象实例(假设其类名为MenuController),并支持从NSMenuDelegate方法继承的2: –NumberOfItems菜单: –菜单:更新项:索引:应取消: 此实例作为蓝色对象添加到NIB中,以便在运行时唤醒 步骤2-3中的对象配置为子菜单的委托(步骤1),cocoa,appkit,nsmenu,Cocoa,Appkit,Nsmenu,现在,我可以在运行时提供子菜单内容 接下来,我将执行以下操作:我可以添加新项或从数组中删除旧项(在包含菜单标题的MenuController中),该数组通过协议和委托映射到真实子菜单。 一切正常。 除了一件事:我喜欢为我的动态菜单项指定快捷方式。 CMD-1、CMD-2、CMD-3等 Window/MySubmenu/MyItem1 CMD-1、MyItem2 CMD-2 所以,对于调用一些我不想去Window/MySubmenu/MyItem用鼠标点击的项目,我只想按一个快捷键,比如CMD-3

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

接下来,我将执行以下操作:我可以添加新项或从数组中删除旧项(在包含菜单标题的MenuController中),该数组通过协议和委托映射到真实子菜单。 一切正常。 除了一件事:我喜欢为我的动态菜单项指定快捷方式。 CMD-1、CMD-2、CMD-3等

Window/MySubmenu/MyItem1 CMD-1、MyItem2 CMD-2

所以,对于调用一些我不想去Window/MySubmenu/MyItem用鼠标点击的项目,我只想按一个快捷键,比如CMD-3来调用该项目

好的,它会按预期周期工作。但是,一般来说,除了打开Window/MySubmenu以重新加载其内容外,我无法将嵌套子菜单的更改通知主菜单。 重现问题的一种稳定方法是,在创建新项目作为“替换已删除项目”后,尝试删除某些项目并按指定给它的旧快捷方式-宾果-在导航到“窗口/我的子菜单”以查看当前子菜单内容之前,快捷方式不起作用

我不知道如何强制主菜单重建其子菜单。。。 我尝试了:[[NSApp Main Menu]update]和使用NSNotificationCenter的游戏,用于发送NSMenudAdItemNotification、NSMenudRemoveItemNotification、NSMenudChangeItemNotification

我试图打开我的子菜单并显式调用update方法-没有办法。。。 有时候AppKit调用我的委托方法——我看到,有时候它不想调用任何东西。看起来像是一个随机策略

如何确保在“某些调用”后,我的子菜单在内部阵列修改后处于实际状态

我试过:[[NSApp主菜单]更新]

你在正确的轨道上。在这种情况下,Cocoa应用程序中的并行阵列可能是有保证的

  • 保持菜单项的可变数组,与菜单项表示的模型对象数组平行
  • 当您收到菜单:中的NumberOfItems时,将您拥有的模型对象数量与菜单项数组的计数进行比较。如果数量较少,请使用以缩短菜单项数组。如果更多,则用对象填充阵列。(此处不能使用
    nil
    ,因为NSArray只能包含对象,
    nil
    表示没有对象。)
  • 当您收到
    菜单:updateItem:atIndex:shouldCancel:
    时,在返回新菜单项之前使用新菜单项
  • 符合NSMenuValidation协议,如中所述。在验证方法中,获取模型对象数组中该索引处的模型对象,并从中更新菜单项。如果您使用的是Snow Leopard,则可以发送菜单项的菜单a,以确定需要从模型对象授予哪些特性值
  • 需要注意的是,此对象(菜单的委托)也必须是菜单项的目标。我想是的。如果不是,则在步骤4失败,因为验证消息被发送到菜单项的目标


    您可能想寻求更好的方法。

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

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


    在代表调用
    numberofitems菜单中:
    call
    removeAllItems
    。。。这很奇怪,但除此之外,菜单不会更新,即使它需要一个代表

    - (NSInteger)numberOfItemsInMenu:(NSMenu*)menu {
    
        [menu removeAllItems];
    
        return [self.templateURLs count] + 2;
    
    }
    

    谢谢彼得。然而,我寻找方法将数组1:1映射到菜单(而不是反向)。我找到了解决方案——就像您所说的。为了防止内存消耗的死环(如果第一次没有使用nil调用初始化菜单),在menuedsupdate中需要一个附加条件:if(!menu)return;/*计数前=*/
    - (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];
    }
    
    [self menuNeedsUpdate:nil];
    
    - (NSInteger)numberOfItemsInMenu:(NSMenu*)menu {
    
        [menu removeAllItems];
    
        return [self.templateURLs count] + 2;
    
    }