0

I found the question Creating NSMenu with NSMenuItems in it, programmatically? but failed to get the solution to work in my application. I tried combining the code from the question and accepted answer to get the following:

NSMenu *fileMenu = [[NSMenu alloc] initWithTitle:@"File"];
NSMenuItem *newMenu = [[NSMenuItem alloc] initWithTitle:@"New" action:NULL keyEquivalent:@""];
NSMenuItem *openMenu = [[NSMenuItem alloc] initWithTitle:@"Open" action:NULL keyEquivalent:@""];
NSMenuItem *saveMenu = [[NSMenuItem alloc] initWithTitle:@"Save" action:NULL keyEquivalent:@""];
[fileMenu addItem: newMenu];
[fileMenu addItem: openMenu];
[fileMenu addItem: saveMenu];
NSMenuItem *fileMenuItem = [[NSMenuItem alloc] init];
[fileMenuItem setSubmenu: fileMenu];
[[NSApp mainMenu] addItem: fileMenuItem];
[fileMenuItem release];

No File menu is created. Placement of the above code before or after the other code in the main function is inconsequential. I also tried placing in applicationDidFinishLauching to no avail. Why does the above code fail to function, and how can I give my application a menu without using any XIB or Storyboard files?

user16217248
  • 3,119
  • 19
  • 19
  • 37
  • 2
    Does this answer your question? [For Objective-C, the nsmenuitem nsmenu menu bar does not display problems](https://stackoverflow.com/questions/68507113/for-objective-c-the-nsmenuitem-nsmenu-menu-bar-does-not-display-problems) – Willeke Aug 24 '22 at 23:03
  • @Willeke The linked answer simply provides an allegedly functioning example. I would prefer an answer that clearly explains where my code has it wrong and what the solution is and *why* the solution works. – user16217248 Aug 27 '22 at 21:41

1 Answers1

-1

You just need to add a menubar in order to get your code to run. Could also use addItemWithTitle: and save a few lines of code. If you don't hook up each menuItem to a method they will be grayed out. -buildMenu is usually called from -applicationWillFinishLaunching: in AppDelegate.

- (void) menuAction: (id)sender {
 NSLog(@"%@", sender);
}

- (void) buildMenu {
// **** Menu Bar **** //
 NSMenu *menubar = [NSMenu new];
 [NSApp setMainMenu:menubar];
// **** App Menu **** //
 NSMenuItem *appMenuItem = [NSMenuItem new];
 NSMenu *appMenu = [NSMenu new];
 [appMenu addItemWithTitle: @"Quit" action:@selector(terminate:) keyEquivalent:@"q"];
 [appMenuItem setSubmenu:appMenu];
 [menubar addItem:appMenuItem];
// **** File Menu **** //
 NSMenuItem *fileMenuItem = [NSMenuItem new];
 NSMenu *fileMenu = [[NSMenu alloc] initWithTitle:@"File"];
 [fileMenu addItemWithTitle:@"New" action:@selector(menuAction:) keyEquivalent:@""];
 [fileMenu addItemWithTitle:@"Open" action:@selector(menuAction:) keyEquivalent:@""];
 [fileMenu addItemWithTitle:@"Save" action:@selector(menuAction:) keyEquivalent:@""];
 [fileMenuItem setSubmenu: fileMenu];
 [menubar addItem: fileMenuItem];
}

apodidae
  • 1,988
  • 2
  • 5
  • 9
  • 2
    Please don't copy answers, mark the question as duplicate instead. – Willeke Aug 25 '22 at 07:37
  • No, I was about to downvote but I didn't. Please don't post a lot of irrelevant code. – Willeke Aug 26 '22 at 08:54
  • If I need to create a main menu first presumably because one does not automatically exist, then why does `[[NSApp mainMenu] addItem: fileMenuItem]` not crash the program for a `nil` reference? – user16217248 Aug 27 '22 at 17:43
  • The code posted doesn't work because [NSApp mainMenu] is null; you have no menubar. True, it doesn't crash, but it also won't work until you create a menubar. I don't know why it doesn't crash (unlike another language I work with) but lucky for us it doesn't. Robust os I guess. – apodidae Aug 27 '22 at 18:17
  • @apodidae But if `[NSApp mainMenu] == NULL` why does calling `addItem` method not even crash? In Objective-C you can call a method on a `NULL` object and silently fail instead of crashing? – user16217248 Aug 27 '22 at 21:47
  • I think that's right. When things don't work as expected in objc you need to start checking values; often an obj is null and that's why it doesn't work. The app doesn't always crash, it just silently fails; are you used to working in Java? – apodidae Aug 27 '22 at 22:15
  • @apodidae Java (Null Pointer Exception), plain C (Segmentation Fault), Swift (Crash from unexpectedly finding NULL in an optional), most languages in fact, will yield some sort of error/crash upon attempting to use a NULL value/pointer in any meaningful way. The fact that Objective-C objects do not do this is confusing. – user16217248 Aug 28 '22 at 15:26
  • I don't think you'll get into too much trouble if you try to use something you never alloc/inited in the first place; if you want to get into trouble, try releasing fileMenuItem before you add it to the menubar, ie move [fileMenuItem release]; up one line of code. Should cause a segmentation fault. Trying to reuse an obj that has been alloc/inited and then released is the trouble maker. – apodidae Aug 28 '22 at 19:38