Objects, Messages, and Targets

The Cocoa Application Kit is written in Objective-C, a hybrid language based on ANSI C and SmallTalk that was developed by Brad Cox. The principal building block of object-oriented programs is the object . Objects can be thought of as bundles of related ANSI C variables and functions with lots of extra functionality.

Objective-C objects are self-contained code entities that communicate by sending messages to one another. A message is like a function call in a traditional programming language in that it causes a procedure to be executed. However, a message is unlike a function call in that it is sent to a specific object; it is not simply “called.” The procedures that are executed — called methods in Objective-C — are “encapsulated” inside objects, and thus different objects can respond to the same message in different ways.

Unlike some object-oriented languages, Objective-C doesn’t require that you know the type (class) of an object before you send it a message. This is known as dynamic or runtime binding; the message is bound to the object at runtime instead of compile-time. It allows for much greater flexibility, because certain decisions can be made following a user’s action. For example, when a user chooses Cut from an application’s Edit submenu, a cut: message is sent to a target object (the colon is part of the message). If an application lets a user cut text, graphics, and other types of data, the cut: message will have varying targets that won’t be known until runtime. With runtime binding, the application doesn’t need to know the class of the target object before the cut: message is sent.

Objects and Classes

Under Cocoa, every on-screen object is represented by an Objective-C object inside the computer’s memory. In our little Noise button application, there’s an NSWindow object that displays and controls the application’s on-screen “Window” window, and there’s an NSButton object that displays and controls the Noise button. There’s yet another object for the application’s “Untitled - MainMenu” window, and one additional object for each of the individual menu items inside the menu.

Every Cocoa object belongs to a class , which both defines and creates the object. Many of the Cocoa class names are fairly self-explanatory. For example, the classes of the on-screen objects in the application we just described are listed in Table 3-1.

Table 3-1. On-screen objects in the application

Object in the application

Class

The window (“Window”)

NSWindow

The button (“Noise”)

NSButton

The main menu (“Untitled”)

NSMenu

The menu items (Info, Edit, Hide, Quit)

NSMenuItem

The “NS” in the prefix to each class name is a holdover from NeXTSTEP (NS), the application framework that spawned Mac OS X.

There are many other objects present in this application that aren’t immediately apparent because they have no obvious corresponding objects on the screen. Some of these objects are listed in Table 3-2.[7]

Table 3-2. Additional objects in the application that aren’t immediately apparent on-screen

Object name

Class

Purpose

NSApp

NSApplication

The application’s main controlling object

[myWindow contentView]

NSView

Defines the content area of the window where the application can draw

n/a

NSButtonCell

The Button’s supporting Cell object, which actually displays the button

Notice that the second object in Table 3-2 has a funny name with square brackets. The square brackets are the Objective-C messaging operator . The phrase “[myWindow contentView]” means “send the contentView message to the object pointed to by the variable called myWindow and return the result.” The result is a pointer to the contentView object (or simply “content view”) inside myWindow. A pointer to an Objective-C object is called an id . When the application starts up, we don’t have the id for myWindow’s content view object. We can get it only by sending a message to the myWindow object (myWindow here is the Objective-C variable name for the pointer that points to the Window object titled “Window”).

Messaging is one of three major elements of the Objective-C language that you need to learn about in order to write Cocoa programs. The second is how to construct your own classes. The third is how to use a few of the important classes that are part of the Cocoa environment — in particular, the classes NSWindow, NSView, and NSApplication. Once you understand these three things, the very heart and soul of Cocoa, you will understand most of what you need to know to write Cocoa programs.

Targets, Actions, and Connections

Many of the objects in Cocoa’s Application Kit are set up so that when you manipulate an on-screen object in a running application, a message is automatically sent to a second object. These objects are called control objects . (The Noise button object we discussed earlier is a control object.) The object that receives the message is called the target of the sending object. The procedure (method) that the target is instructed to perform is called the action . We’ll refer to this as the target/action paradigm .

For example, when you choose the Quit menu command from an application’s menu, the associated NSMenuItem object sends a terminate: message to the control object, NSApp (also known as the File’s Owner).

The terminate: message has the form [NSApp terminate:self] . The action is terminate:, and self is an argument specifying the object that sent the message. This message causes the NSApp object to execute its terminate: method, which terminates the program. Likewise, the NSMenuItem object associated with the Hide menu command sends the hide: message to NSApp, which causes NSApp to remove all of the application’s windows from the screen. Note that the colons (: ) shown above are actually part of the Objective-C method names.

To see how this works in practice, let’s add two more control objects — a text field and a slider — to the new application’s window. First we’ll put them in the window, and then we’ll wire (connect) them together so that a message can be sent from the slider to the text field.

  1. Return to the application you built previously within IB’s Build mode.

  2. Drag the icon for the simple NSTextField object from the Cocoa-Views Palettes window into the window titled “Window”.

  3. Click the Cocoa-Other button at the top of the Palettes window to display the sliders available to applications under construction.

  4. Drag the icon for the horizontal grid slider object from the Cocoa-Other Palettes window into the window titled “Window”.

  5. When you’re done, you should have a window that looks like the one in Figure 3-12.

Window with new text field and slider in IB

Figure 3-12. Window with new text field and slider in IB

Next, we’ll make a connection so that the slider (NSSlider) object can send a message to the text field (NSTextField) object whenever the slider’s knob is moved.

  1. Hold down the Control key on the keyboard and drag from the slider object to the text field object (note the direction). You will see a “connection wire” linking the slider to the text field, as shown in Figure 3-13.

Connection wire from slider to text field in IB

Figure 3-13. Connection wire from slider to text field in IB

  1. Release the mouse button, and IB’s Connections Info dialog (NSSlider Info) will appear near the lower-right corner of the screen (see Figure 3-14). The Connections Info dialog lets you make or break connections between objects.

Connections and attributes of NSSlider object

Figure 3-14. Connections and attributes of NSSlider object

Connections from a control object (i.e., the slider) to another object have two parts: a target and an action. You already specified the NSTextField object as the target (or receiver or destination) of a message when you connected the NSSlider object to the NSTextField object (in that direction). You specify which action (method) the target should perform in response to an event in the NSSlider Info dialog. Your choices for the action are listed under “Actions” in the Info dialog on the left of Figure 3-14. (If you had connected the NSSlider object to a different target, such as the NSButton object, you would see a different list of actions, because an NSButton object can perform a different set of actions from those performed by an NSTextField object.)

The action we’ll use here is takeIntValueFrom: , which causes the NSTextField object to ask the sender (the NSSlider object) of the original message for its integer value (only the grid marks have values on this particular slider). This integer corresponds to the position of the NSSlider object’s knob.

  1. Select the takeIntValueFrom: action in the Connections Info dialog and then click the Connect button. (Alternatively, you can double-click the takeIntValueFrom: action.)

After you make the connection, the Connect button becomes a Disconnect button, as in the inspector window on the left of Figure 3-14, and the connection dimple appears next to the action name in the Info dialog.

  1. Make sure the slider is selected (handles appear), then choose Attributes from the pop-up menu in the NSSlider Info dialog.

  2. Change the Maximum value of the slider from 100.0 to 1000.0 and change the Current value to 200.0. Note the other attributes, such as Marker Values Only, in the Info dialog on the right of Figure 3-14.

  3. Test the interface again by choosing IB’s File Test Interface menu command or typing Command-R.

  4. Drag the NSSlider object’s knob. As you move it, the NSTextField object will update the integer it displays according to the knob’s position (see Figure 3-15).

Testing the slider connection to the text field in Test Interface mode

Figure 3-15. Testing the slider connection to the text field in Test Interface mode

  1. Choose Quit NewApplication from IB’s main menu.

Figure 3-16 shows the communication between the NSSlider and NSTextField objects. A mouse-drag event on the slider knob causes the NSSlider object to send the takeIntValueFrom: message to the target NSTextField object, which executes its takeIntValueFrom: method (this results from the connection we set up). The takeIntValueFrom: method then sends the intValue message back to the NSSlider object, which returns the slider’s current value of 700 to the NSTextField object, and then the NSTextField object displays the result. (We didn’t have to tell the NSTextField object’s takeIntValueFrom: action procedure to send the intValue message back to the NSSlider object; the NSTextField object is smart enough to know how to get an integer value from the sending object.)

Communication between NSSlider and NSTextField objects

Figure 3-16. Communication between NSSlider and NSTextField objects

This may seem like a lot of overhead, but messaging is actually quite fast — only slightly slower than a standard function call. And the benefits are wonderful, as we’ll see.

  1. Quit IB. There’s no need to save any of the files or interface specifications.



[7] It’s not imperative that you understand everything in the remainder of this section right now, but we’re going to give it to you anyway. We’ll return to these subjects in later chapters.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.31.163