3.2 Nibs

One of the crown jewels of the Cocoa development environment is Interface Builder, a tool for building graphical user interfaces.

Interface Builder creates and stores user interfaces in nib files. Perhaps one of the most important aspects of Interface Builder is that it does not generate source code. Nibs are bundles that contain information and archived objects (in this context often referred to as "freeze-dried") that constitute the elements of the user interface (such as windows, widgets and menus, as well as non-UI objects) as they were arranged and configured with Interface Builder. When a nib file is loaded at run time, the elements are reconstituted exactly as they were in Interface Builder.

Every application has a MainMenu.nib file that contains the application's main menu structure. For simple applications, this nib might also contain the application's main window. More advanced applications generally have a number of nib files, each of which defines part of the user interface.

From a design perspective, creating a nib for each window (or logical group of windows) facilitates reuse. From a performance perspective, loading nibs into memory takes time, so it is best to keep them small. Thus, when the application launches, it needs to load only the nib containing the first window the user sees, rather than every window in the application, many of which the user may never open (such as the About Box).

3.2.1 Outlets and Actions

Nib files contain definitions for objects that can send messages to other objects in the nib file and be assigned to instance variables of other objects. An object instance variable in Interface Builder is known as an outlet. Outlets can be connected to other objects within the nib, and the source code for the class containing the outlet can reference those other nib objects through the outlet instance variable. Objects in nibs also have actions, which are methods that other objects may invoke in response to some event, such as a user clicking a button.

When designing a class in Interface Builder, you can create skeleton source files containing instance variables and stubs for action method definitions. In the header file of a class defined in Interface Builder, outlet instance variables have the IBOutlet type modifier and action methods have an IBAction return type, which is synonymous with void. These modifiers help Interface Builder parse class interfaces when importing classes.

When importing class interfaces, Interface Builder recognizes any instance variable of type id as an outlet. You can statically type an instance variable and have Interface Builder import it as an outlet by prepending the type with the IBOutlet modifier. Both of these instance variables are recognized as an outlet:

id statusTextField;
IBOutlet NSTextField *statusTextField;

However, the following instance variable will not be recognized as an outlet, since it is statically typed and doesn't have the IBOutlet modifier:

NSTextField *statusTextField;

Interface Builder recognizes methods as actions if they have a void return type and a single parameter named sender. The type of the sender parameter can be id, or a class such as NSButton. Interface Builder looks for the sender parameter name as keyword when parsing methods for actions. If you want more meaningful argument names you can explicitly state that a method is an action using the IBAction return type. Interface Builder would recognize the following lines as action methods:

- (void)anAction:(id)sender;
- (void)aButtonAction:(NSButton *)sender;
- (IBAction)aButtonAction:(NSButton *)aButton;

However, the following example is not recognized as an action, since the argument is statically typed, not named sender, and the return type is not IBAction:

- (void)aButtonAction:(NSButton *)aButton;

At any point during the execution of an application, you can load additional nibs. The Application Kit extends the Foundation class NSBundle (discussed in Chapter 2) to provide the ability to load nibs. The most straightforward way to load a nib is with the method loadNibName:owner:. This method searches the application bundle for the best localized nib file variant with the specified name and loads it into memory.

The owner: parameter lets you specify an object that will be the nib's owner. This object can be referenced by other objects in the nib file through the File's Owner proxy object, as illustrated in Figure 3-2. By importing the header for the class of object that will load the nib, you can assign the class for the File's Owner from the Info panel's Custom Class pane. This lets you use the outlets and actions of this class to define connections to objects within the nib.

File's Owner is only a "promise." It does not guarantee that at runtime, the object will be an instance of the specified class. The developer is responsible for ensuring that the object specified in owner: is an instance of the appropriate class.

Figure 3-2. The File's Owner relationship between a nib and an object in an application

    Part II: API Quick Reference