Working without a nib, Part 4: setAppleMenu

Wow, this series already has four parts. It’s entering Rocky territory, having already surpassed Rambo. If I continue much longer I’ll be typecast — (NSNib *)jeff — and no one will remember my work on Vienna or my poignant portrayal of Hamlet (in the community theater production of Guys and Dolls).

A comment by Jack Nutting inspired me to run some additional tests. As the-programmer-currently-known-as-j-o-a-r (formerly known as horse-spear) mentioned in another comment, you can use the method -[NSApplication setAppleMenu:] to set the application menu. The catch is that it’s been removed from the public API and is no longer declared in NSApplication.h. To call the method, you have to declare it yourself in a category:

@interface NSApplication (NiblessAdditions)
-(void) setAppleMenu:(NSMenu *)aMenu;

You could also avoid the need for a category declaration by using [NSApp performSelector:NSSelectorFromString(@"setAppleMenu:") withObject:aMenu].

My tests revealed that AppKit does call -[NSApplication setAppleMenu:] when loading the main menu from a nib, so it appears that this method is no more (or less) fragile than the technique I discovered in Part 2. As far as I can tell, setAppleMenu: sets the title of the menu to @"Apple" and the name of the menu to @"NSAppleMenu", which is why my technique is functionally equivalent. (The method -[NSApplication setMainMenu:] sets the name of the menu to @"NSMainMenu", so my [mainMenu setValue:@"NSMainMenu" forKey:@"name"] isn’t strictly necessary.) It’s a mystery why Apple ‘disappeared’ the method. Maybe it will magically return in a later operating system, with a long beard and a dark tan.

I’m not aware of a method, hidden or otherwise, to set the recent documents menu. Thus, my technique of calling [openRecentMenu setValue:@"NSRecentDocumentsMenu" forKey:@"name"] still seems necessary. Chasing around a little chicken, though, just seems unnecessary and not very mature.

2 Responses to “Working without a nib, Part 4: setAppleMenu”

  1. Christian says:

    Why are you using “NSSelectorFromString(@”setAppleMenu:”)” and not @selector(setAppleMenu:)?

  2. Jeff says:

    Christian, good question. I thought that there might be a problem because setAppleMenu: isn’t declared anywhere, but it turns out I was wrong. It seems to work fine to use @selector(setAppleMenu:).