How Menus Work

The classes NSMenu and NSMenuItem are the basis for all types of menus. An instance of NSMenu manages a collection of menu items and draws them one beneath another. An instance of NSMenuItem represents a menu item; it encapsulates all the information its NSMenu object needs to draw and manage it, but does no drawing or event-handling itself. Generally, you use Interface Builder to create and modify any type of menu. However, NSMenu and NSMenuItem provide you with methods to change your application's menus dynamically.

Menu Basics

Cocoa gives you a core set of classes that handle menus no matter where they appear. Menus commonly appear in various parts of the user interface:

The classes NSMenu and NSMenuItem are the basis for all types of menus. An instance of NSMenu manages a collection of menu items and draws them one beneath another. An instance of NSMenuItem represents a menu item; it encapsulates all the information its NSMenu object needs to draw and manage it, but does no drawing or event-handling itself.

Menu views are capable of having one attached menu view at any given time. An attached menu view displays the contents of a submenu and is typically positioned next to the menu item with which it is associated.

NSMenuItem lets you set the titles, actions, targets, tags, images, enabled states, and similar attributes of individual menu items, as well as to obtain the current values of these attributes. Whenever an attribute for a menu item changes, it notifies its associated NSMenu with the itemChanged: method.

You typically use Interface Builder to create and modify any type of menu, so often there is no need to write any code. However, NSMenu and NSMenuItem provide you with methods to change your application's menus dynamically, in particular to allow you to enable and disable existing menu items (see Enabling Menu Items).

Application Menus

All of an application’s menus in the menu bar are owned by one NSMenu instance that’s created by the application when it starts up. You can retrieve this main menu with the NSApplication method mainMenu.

Application menus drop down from the menu bar when the user clicks in a menu’s title, and submenus appear to the right or left of their menus, depending on the available screen space.

Pop-Up Buttons and Pull-Down Lists

Pop-up buttons are implemented by the NSPopUpButton class. You can choose from a pop-up list or a pull-down list, with the setPullsDown: method:

An NSPopUpButton object contains an NSPopUpButtonCell object. The button contains the button’s data, and the cell controls the button’s appearance. Generally, you’ll invoke methods on the NSPopUpButton object, although most of the work is handled by the NSPopUpButtonCell instance. Most of NSPopUpButton‘s methods are convenience methods which simply invoke the same method on the cell.

To implement its menu, the button cell contains an NSMenu object, which in turn contains several NSMenuItem objects, one for each item in the menu. Avoid invoking methods on the NSMenu object directly, but instead invoke methods on the NSPopUpButton instance, which may need to do some housekeeping before invoking the appropriate methods on the menu. However, you can retrieve the menu with the NSPopUpButton method menu. The NSPopUpButton methods you use most often are the methods that tell you which item is selected.

Generally, you create an NSPopUpButton object with Interface Builder. You can define the NSPopUpButton object’s target and action, as well as the targets and actions of each item in the button’s list, programmatically or through Interface Builder.

Contextual Menus

You can attach a contextual menu to any NSView object. When the user Control-clicks on that view, the menu appears. To assign a menu to a view, use setMenu:, which NSView inherits from NSResponder.

Your subclass can define a menu that’s used for all instances by implementing the defaultMenu class method. To change the menu displayed based on the mouse event, override the menuForEvent: instance method. This allows the view clicked to display different menus based on the location of the mouse and of the view’s state, or to change or enable individual menu items based on the commands available for the view or for that region of the view.