Cocoa Menus
Inserting a Cocoa menu from a nib file
![]()
There's way too much confusion about Cocoa menus on Mac OS X out there.
It's not that hard. Allow me to demystify Cocoa menus for you.
There are a few simple basics about Cocoa menus you will need to know first:
1 - Menus are handled in Cocoa by 2 classes: NSMenu and NSMenuItem.
2 - Your application's menu bar is an instance of NSMenu.
3 - The individual menus in your application's menu bar are each
actually an NSMenuItem with an NSMenu submenu attached to them. Your application's menus are not NSMenus.
4 - It's very easy to insert and remove entire menus in your menubar, but you need to do some setup first.
Here's a tutorial which shows how:
Start a new application project in Xcode by selecting New Project... from the File menu.
Select Cocoa Application under Mac OS X from the list.
Next, open the MainMenu.nib file in Interface Builder - which will look like this:

From the Library palette, drag 2 new NSMenu objects and drop them on your .nib file's window:

These are the two menus we'll insert in the menubar when our app runs.
Single-click each menu in the .nib file window and give each menu a name:

Next, single-click each menu and in the Inspector pallette, enter the Title to match the same name as the name you gave
the menus in the main .nib window:

Next, edit the items of both menus in the .nib window by double-clicking them. You can give the items
any names you wish since this is just a tutorial:


This concludes the NSMenu setup in the .nib file.
Next, we'll write some code to connect the menus to our app.
Go back to Xcode, and open the UntitledAppDelegate.h file. Just below the NSWindow declaration,
add three NSMenu outlets - 1 for the menubar, and 2 for the NSMenus we just created. The 2 outlets for the
menus we created need to be IBOutlets, the other one doesn't:

Next go to UntitledAppDelegate.m and add an awakeFromNIB method:

Add an NSMenuItem local variable to the top of the method:

Next, we need to connect the app delegate's rootMenu outlet that we created to the app's menubar. We could also
do this in Interface Builder but for now, do it in code. Saving the menubar off in the app's controller class caches
it for better performance and easier code. Add this to the awakeFromNib method also:
![]()
Save the source files in Xcode and go back to Interface Builder and connect the 2 NSMenus we created to the outlets in the code:
1 - Control click on the Untitled App Delegate object to bring up its connections window:

2 - Control drag from the menu1 & menu2 outlets' empty circles in the connections window to each of the NSMenus we created earlier:

Close the connections window, save the .nib file, and go back to Xcode.
At this point if you put a breakpoint at the end of the awakeFromNib method and run the app, you'll see the 3 menus we added to our app delegate's header loaded:

To recap - rootMenu is the instance of our app's main menubar, and menu1 & menu2 and instances of the 2 menu objects we created in the .nib file.
Next, we're ready to insert the two menus into our menubar. This is the confusing part.
What we need to do for each menu we want to insert in the menubar is:
1 - Create a temporary NSMenuItem which we will throw away later.
2 - Attach our loaded NSMenus to each NSMenuItem, respectively.
3 - Insert the NSMenuItems into the menubar at specified indicies.
Ok, so let's do it.
Add a second NSMenuItem at the top of awakeFromNib:

Next, create 2 temporary menu items. The titles are the text that will appear in the menubar for each menu.
We will attach our menus from the .nib file to these in the next step.

Next attach the 2 NSMenu instances to the NSMenuItems:

Now set both menu items into the menubar at indicies 4 & 5, respectively:

Save all files and run the app:

Voila! Instant menus.
That wasn't so bad was it?
In a real app we would also connect each menu item in the NSMenus to action methods in our app controller, or in some other object.
(They are greyed out in our sample app because we haven't connected the menu items to anything yet).
The important things to remember here are:
1 - The menubar is an NSMenu.
2 - The individual menus are NSMenus each attached to an NSMenuItem as a submenu.
3 - It's the NSMenuItems that get inserted into the menubar, not the NSMenus.
4 - In order to make menus that work, the NSMenuItems you insert into the menubars must have submenus attached to them.
Our final awakeFromNib method looks like this:

From this basic code you should now understand how to create and insert menus into the menubar.
The key to all this is to create the individual menu outlets in your app's controller plus one for the menubar itself.
Once you have those cached, it becomes much easier to manipulate menus later on in your program.
Connecting the NSMenus in Interface Builder to the outlets in your app's controller makes the task of loading the menus at runtime vastly easier.
Using code like the above you should be able to create several methods for adding, removing, and renaming menus and menu items easily.
This approach will make the use of dynamic menus in your app much simpler and easier to deal with.
I hope you enjoyed this tutorial - if you have any questions or comments, email me at:
<info @ michael-amorose <dot> com>
![]()