2

I have an NSMenu (let's say the Main Menu), with lots of NSMenus in it, and NSMenuItems at different levels.

I want to be able to get the NSMenuItem instance specifying the tree path (with the title of the corresponding NSMenus/NSMenuItems in it).

Example :

Menu :

  • File
    • New
    • Open
      • Document
      • Project
    • Save
    • Save As...

Path : /File/Open/Document

How would you go about it, in the most efficient and Cocoa-friendly way?

Dr.Kameleon
  • 22,532
  • 20
  • 115
  • 223

2 Answers2

3

I think that best way would be to obtain the NSMenuItem by specifying its title or, better, a custom defined tag.

#define kMenuFileNew 1
#define kMenuFileOpen 2

NSMenu *menu = [[NSMenu alloc] initWithTitle:@"File"];
NSMenuItem *item1 = [[NSMenuItem alloc] initWith..];
item1.tag = kMenuFileOpen;
[menu addItem:item1];


NSMenuItem* item2 = [menu itemWithTag:kMenuFileOpen];
Jack
  • 131,802
  • 30
  • 241
  • 343
  • Sure, but what I'm trying to do is not just get an NSMenuItem; but an NSMenuItem inside an NSMenu inside another submenu, etc... by specifying a path of titles... :-) (I'm working on it right now, let's see...) – Dr.Kameleon Mar 24 '12 at 13:23
  • I made it!!! Yeah! I'm posting the solution as an answer for the community... :-) – Dr.Kameleon Mar 24 '12 at 13:33
2

So, here it is; solved by creating a Category on NSMenu, and using recursion.

Code :

- (NSMenuItem*)getItemWithPath:(NSString *)path
{
    NSArray* parts = [path componentsSeparatedByString:@"/"];
    NSMenuItem* currentItem = [self itemWithTitle:[parts objectAtIndex:0]];

    if ([parts count]==1)
    {
        return currentItem;
    }
    else
    {
        NSString* newPath = @"";

        for (int i=1; i<[parts count]; i++)
        {
            newPath = [newPath stringByAppendingString:[parts objectAtIndex:i]];
        }

        return [[currentItem submenu] getItemWithPath:newPath];
    }
}

Usage :

NSMenuItem* i = [mainMenu getItemWithPath:@"View/Layout"]; 
Dr.Kameleon
  • 22,532
  • 20
  • 115
  • 223
  • Can I ask why you are doing this? It seems you should already know the menu item since you made the title in IB and could easily tag each menu. Or if you do them programmatically again you should know each one's id... – markhunte Mar 24 '12 at 14:21
  • 1
    @markhunte Well, I have a VERY EXPANDED Main menu with lots of nested submenus/items, etc... and wanted a FAST one-liner so that I can reference any menu item, without having to create outlets for all of them, or tag them, etc... (The code base I'm working on is quite HUGE and I'm trying to keep it as readable and minimal as possible...) :-) – Dr.Kameleon Mar 24 '12 at 14:25
  • This will fail if the user's computer is localized to any non-english language or if Apple changes the title of an item in a future OS update. – Nathan Kinsinger Mar 24 '12 at 18:19