In Interface Builder, you specify the paths for messages traveling between the controller and other objects as outlets and actions. The following sections explain how the objects that implement the Currency Converter user interface communicate with each other in the running application.
Outlets
Target/Action in Interface Builder
Which Direction to Connect?
An outlet is an instance variable that identifies an object. Figure 5-1 illustrates how an outlet in one object points to another object.
Objects can communicate with other objects in an application by sending messages to outlets. An outlet can reference any object in an application: user interface objects such as text fields and buttons, windows and dialogs, instances of custom classes, and even the application object itself. What distinguishes outlets is their relationship to Interface Builder.
Outlets are declared as:
IBOutlet id variableName;
Note: IBOutlet is a null-defined macro, which the C preprocessor removes at compile time. Interface Builder uses it to identify outlet declarations so that it can display them when connecting outlets visually.
Objects with id as their type are dynamically typed, meaning that the class of the object is determined at runtime. You can use id as the type for any object. The dynamically typed object’s class can be changed as needed, even during runtime, which should invoke a sense of both excitement and extreme caution in even the most grizzled OO veteran. This can be a tremendous feature and allows for very efficient use of memory, but casting a type to an object that cannot respond to the messages for that type can introduce puzzling and difficult-to-debug problems into your application.
When you don’t need a dynamically typed object, you can—and should, in most cases—statically type it as a pointer to an object:
IBOutlet NSButton* myButton;
You usually set an outlet’s target in Interface Builder by drawing connection lines between objects. There are ways other than outlets to reference objects in an application, but outlets and the ability of Interface Builder to initialize them are a great convenience.
At application load time, the instance variables that represent outlets are initialized to point to the corresponding target. For example, the parameter of the controller instance that receives the value from the exchange rate in the view would be initialized with a reference to the Exchange Rate text field object (see “Connect the ConverterController Instance to the Text Fields” for details). When an outlet is not connected, the value of the corresponding instance variable is null.
It might help to understand connections by imagining an electrical outlet plugged into the destination object. Also picture an electrical cord extending from the outlet in the source object. Before the connection is made, the cord is not plugged in, and the value of the outlet is null; after the connection is made (the cord is plugged in), a reference to the destination object is assigned to the source object’s outlet.
You can view (and complete) target/action connections in the Connections pane in the Interface Builder inspector. This pane is easy to use, but the relation of target and action in it might not be apparent. First, a target is an outlet of a cell object that identifies the recipient of an action message. Well, you may say, what’s a cell object and what does it have to do with a button?
One or more cell objects are always associated with a control object (that is, an object inheriting from NSControl, such as a button). Control objects “drive” the invocation of action methods, but they get the target and action from a cell. NSActionCell defines the target and action outlets, and most kinds of cells in the Application Kit inherit these outlets.
For example, when a user clicks the Convert button in the Currency Converter window, the button gets the required information from its cell and invokes the convert method on the target outlet object, which is an instance of the custom class ConverterController. Figure 5-2 shows the interactions between the ConverterController class, the Convert button, and the Amount in Other Currency: field.
In the Actions column (in the Connections pane of the inspector), all action methods are defined by the class of the target object and known by Interface Builder. Interface Builder identifies action methods because their names follow this syntax:
- (IBAction)myAction:(id)sender; |
Note: IBAction, like IBOutlet, is a null defined macro, which the C preprocessor removes at compile time. Interface Builder uses it to identify action declarations so that it can display them when connecting actions visually.
Here, it looks for the argument sender.
Usually the outlets and actions that you connect belong to a custom subclass of NSObject. For these occasions, you need only to follow a simple rule to know in which way to specify a connection in Interface Builder. Create the connection from the object that sends the message to the object that receives the message:
To make an action connection, create the connection from an element in the user interface, such as a button or a text field, to the custom instance you want to send the message to.
To make an outlet connection, create the connection from the custom instance to another object (another instance or user interface element) in the application.
These are only rules of thumb for common cases and do not apply in all circumstances. For instance, many Cocoa objects have a delegate outlet. To connect these, you draw a connection line from the Cocoa object to your custom object.
Another way to clarify connections is to consider who needs to find whom. With outlets, the custom object needs to find some other object, so the connection is from the custom object to the other object. With actions, the control object needs to find the custom object, so the connection is from the control object to the custom object.
Last updated: 2007-10-31