Documentation Archive Developer
Search

Configuring the Window

Xcode provides a library of objects that you can add to a window or view. The TrackMix app already contains a window—now you need to add a text field, slider, and button. Then, you make connections between these elements and your classes, and implement the behavior you want in the next chapter.

image: ../Art/TrackMixViews.png

Add the UI Elements

You add UI elements by dragging them from the object library to a view or window. After the UI elements are added, you can move, resize, and configure them as needed.

bullet
To add the UI elements to the window
  1. In the project navigator, under the TrackMix group, select the MainMenu.xib file to display the TrackMix window.

  2. If necessary, click the rightmost View button in the toolbar to display the utility area at the right side of the window.

    image: ../Art/utility_button.png
  3. If necessary, click the window object icon in the editor area to display the window.

  4. In the editor area, make the window narrower by dragging the three dots that appear adjacent to the window’s corners and edges.

    image: ../Art/9_ib_objectlibrary.png
  5. If necessary, open the object library.

    The object library appears at the bottom of the utility area. If you don’t see the object library, you can click its button, which is the third button from the left in the library selector bar:

    image: ../Art/9b_objectlibrarybutton.png
  6. In the object library, choose Cocoa > Controls from the Object Library pop-up menu.

    Xcode displays a list of controls below the pop-up menu. The list displays each control’s name, an image, and a short description of its function.

  7. One at a time, drag a text field, a vertical slider, and a push button from the list and into the window.

    You can use the search field at the base of the utility area to find the objects you want and drag them to the window.

    image: ../Art/9c_objectlibrarysearch.png

You resize the items using resize handles, where appropriate, and reposition them by dragging. As you move items within the view, alignment guides are displayed as dashed blue lines.

bullet
To lay the UI elements out appropriately
  1. Drag the text field so that it’s near the top of the window and centered horizontally.

    As you move the text field (or any UI element), dashed blue lines—called alignment guides—appear that help you align the item with the center and edges of the view. Stop dragging the text field when you can see the view’s center and upper alignment guides, as shown here:

    image: ../Art/13_dragtextfield.png
  2. Drag the vertical slider so that it appears centered and below the text field.

  3. In the view, prepare to resize the vertical slider.

    You resize a UI element by dragging its resize handles, which are small white squares that can appear on the element’s borders. In general, you reveal an element’s resize handles by selecting it. If your vertical slider looks like the one below, you’re ready to resize it; if it doesn’t, select it on the canvas.

    image: ../Art/14_resizeslider.png
  4. Drag the vertical slider’s lower resize handle until the window’s center alignment guide appears.

    Stop resizing the text field when you see something like this:

    image: ../Art/15_stopresizeslider.png
  5. Drag the button so that it’s near the bottom of the window (below the vertical slider) and centered horizontally.

After you add the text field, vertical slider, and push button UI elements and make the recommended layout changes, your project should look similar to this:

image: ../Art/10_ib_layout.png

You can specify some of the UI elements’ behavior and appearance using the Attributes inspector. Add a default string 5 to the text field, configure the vertical slider to have minimum and maximum values, and set the title of the button to Mute.

bullet
To configure the text field
  1. Click the text field to select it and open the Attributes inspector (if necessary) by clicking the icon that looks like this: image: ../Art/attributes_icon.jpg

  2. In the Title text field at the top of the Text Field Attributes inspector, enter 5.

    This is the initial value of the text field. Alternatively, double-click the text field in the TrackMix window and enter the number directly.

  3. Click the Align Center button to center the text field’s text.

    After you enter the text and change the alignment setting, the Text Field Attributes inspector should look like this:

    image: ../Art/16_textfieldattrinsp.png
bullet
To configure the slider
  1. In the editor area, select the slider.

  2. In the Value section’s Minimum field of the Slider Attributes inspector, enter zero (0).

  3. In the Value section’s Maximum field, enter 11.

  4. In the Current Value field, enter 5 (to match the text field).

  5. Scroll down to the Control attributes (if necessary) and select the Continuous checkbox.

    If the slider is continuous, it sends messages while it’s being moved rather than only when a new value is set.

    After you change the slider setting, the Slider Attributes inspector should look like this:

    image: ../Art/17_sliderattrinsp.png
bullet
To configure the button

Do one of the following:

  • Double-click inside the button, type Mute, and press Tab.

  • Select the button, type Mute in the Title field of the Button Attributes inspector, and press Tab.

Optionally, click the Run button (or choose Product > Run) to make sure that the UI elements you added look the way you expect them to. You should see something like this:

image: ../Art/18_runtrackmix.png

You can interact with the UI elements but at the moment, the Mute button doesn’t do anything, the text field input doesn’t move the slider’s knob, and the slider doesn’t change the value displayed by the text field. To add this functionality, you need to make the appropriate connections between the UI elements and write some code. These connections are described next.

Create Actions for the Button, Text Field, and Slider

When the user activates a UI element, the element can send a message to an object that knows how to perform the corresponding action. This interaction is part of the target-action mechanism, a Cocoa design pattern.

In this tutorial, when the user clicks the Mute button, you want it to send a “set the track’s volume to zero” message (the action) to the app delegate (the target). In this case, the app delegate acts as a view controller in the Model-View-Controller design pattern. This action message changes the “model” data (the track’s volume) that the app delegate manages. Then, the app delegate updates the other views (the slider and text field) to reflect the change in the model object’s data. You’ll create the model object that represents the track later.

image: ../Art/TrackMixVC.png

Using Xcode, you can set an action for a UI element and set up its corresponding action method by Control-dragging from the element on the canvas to the appropriate source file (for example, to the AppDelegate class source file). The connections that you create in this way are archived, along with the UI elements, in the nib file. Later, when the app loads the nib file, the connections are restored.

bullet
To add an action for the button
  1. If necessary, select MainMenu.xib in the project navigator to display the app window.

  2. In the Xcode toolbar, click the Utilities button (the rightmost View control) to hide the utility area and click the Assistant editor button to display the assistant editor pane.

    The Assistant editor button is the middle Editor button and it looks like this: image: ../Art/assistant_editor_button.jpg.

  3. Make sure that the assistant editor displays the AppDelegate class header file (that is, AppDelegate.h).

    Select AppDelegate.h from the Top Level Objects menu at the top of the assistant editor.

    image: ../Art/18b_assistantmenu.png
  4. On the editor, Control-drag from the Mute button to the method declaration area in AppDelegate.h (that is, between the @interface statement and the @end statement).

    To Control-drag, press and hold the Control key while you drag from the button to the header file in the assistant editor pane.

    image: ../Art/19a_buttonconnection.png

    When you release the Control-drag, Xcode displays a popover in which you can configure the action connection you just made.

    image: ../Art/19_buttonconnection.png
  5. In the popover, configure the button’s action connection:

    • In the Connection pop-up menu, choose Action.

    • In the Name field, enter the method name mute:.

      In a later step, you’ll implement the mute: method to set the volume to zero.

    • Make sure that the Type field contains id.

      The id data type can represent any Cocoa object. You want to use id here because it doesn’t matter what type of object sends the message.

    After you configure the action connection, the popover should look like this:

    image: ../Art/20_buttonconnection2.png
  6. In the popover, click Connect.

    Xcode adds a method declaration to the header file and a stub for the new method to the implementation file. Xcode indicates that the connection has been made by displaying a filled-in circle to the left of the method:

    image: ../Art/21_buttonactionmethod.png
bullet
To add an action for the text field
  1. Control-drag from the text field to the method declaration area in AppDelegate.h.

    image: ../Art/22a_textfieldconnection.png
  2. In the popover that appears when you release the Control-drag, configure the text field’s action connection:

    • In the Connection pop-up menu, choose Action.

    • In the Name field, enter takeFloatValueForVolumeFrom:.

      In a later step, you’ll implement the takeFloatValueForVolumeFrom: method to set the model data and synchronize the text field with the slider.

    • Make sure that the Type field contains id.

  3. In the popover, click Connect.

    Xcode adds a method declaration to the header file and a stub for the new method to the implementation file. Xcode indicates that the connection has been made by displaying a filled-in circle to the left of the method:

    image: ../Art/22_textfieldactionmethod.png

You accomplished two things by Control-dragging from the button and text field to the AppDelegate.h header file:

Control-dragging from a UI element to source code is a convenient shortcut for creating a connection to an object and adding an action or outlet to its class . If the action or outlet already exists, you Control-drag directly to or from it.

Because the slider can use the same takeFloatValueForVolumeFrom: method as the text field uses, you simply connect it to the app delegate object to set the slider’s target and action. You can do this because the action method was added to the AppDelegate class in a previous step.

bullet
To set the slider's target and action
  1. In the editor area, Control-drag from the slider to the App Delegate blue cube that appears on the left side of the editor area below the window icon (the blue cube represents an object).

    Xcode displays a list of action methods implemented by the AppDelegate class.

    image: ../Art/22b_slideraction.png
  2. When you release the Control-drag, select the takeFloatValueForVolumeFrom: method to make the connection.

Create Outlets for the Text Field and Slider

An outlet describes a connection between two objects. When you want an object (such as the app delegate) to communicate with an object in the nib file (such as the text field), you designate the contained object as an outlet. When the nib file is loaded at runtime, the outlet you create in Xcode is restored, which allows the objects to communicate with each other.

In this tutorial, you want the app delegate to get the user’s text from the text field, set the volume accordingly, and update the slider. To allow the app delegate to communicate with these objects, you create outlet connections for each. You need an outlet only for the text field and slider. You don’t need an outlet for the button because the app delegate doesn’t need to send messages to the button.

The steps you take to add outlets for the text field and slider are very similar to the steps you took when you added the button’s action. Before you start, make sure that the MainMenu.xib file is still visible in the editor and that AppDelegate.h is open in the assistant editor.

bullet
To add an outlet for the text field
  1. Control-drag from the text field in the window to the method declaration area in the interface file.

    It does not matter where you release the Control-drag as long as it’s inside the method declaration area. In this tutorial, the new outlets appear below the window outlet declaration.

  2. In the popover that appears when you release the Control-drag, configure the text field’s connection:

    • Make sure that the Connection pop-up menu contains Outlet.

    • In the Name field, enter textField.

      You can call the outlet whatever you want, but your code is more understandable when an outlet name bears some relationship to the item it represents.

    • Make sure that the Type field contains NSTextField.

      Setting the Type field to NSTextField ensures that Xcode connects the outlet only to a text field.

    • Make sure that the Storage pop-up menu contains Weak, which is the default value for outlets.

    After you make these settings, the popover should look like this:

    image: ../Art/23_textfieldconnection.png
  3. In the popover, click Connect.

    Xcode adds a declaration for the outlet and indicates that the connection has been made by displaying a filled-in circle to the left of the method:

    image: ../Art/24_textfieldoutlet.png
bullet
To add an outlet for the slider
  1. Control-drag from the slider in the window to the method declaration area in the header file.

  2. In the popover that appears when you release the Control-drag, configure the slider’s connection:

    • Make sure that the Connection pop-up menu contains Outlet.

    • In the Name field, enter slider.

    • Make sure that the Type field contains NSSlider.

    • Make sure that the Storage pop-up menu contains Weak.

    After you make these settings, the popover should look like this:

    image: ../Art/25_sliderconnection.png
  3. In the popover, click Connect.

You accomplished two things by adding outlets for the text field and slider:

At this point in the tutorial, you’ve created a total of five connections to the app delegate object:

You can verify these connections in the Connections inspector.

bullet
To open the Connections inspector for the app delegate
  1. While viewing the MainMenu.xib file, click the Standard editor button to close the assistant editor and switch to the standard editor view.

    The Standard editor button is the leftmost Editor button and it looks like this: image: ../Art/standard_editor_button.jpg

  2. Click the Utilities view button to open the utilities area.

  3. Select App Delegate in the editor area (the blue cube located under the window icon).

  4. Show the Connections inspector in the utilities area.

    The Connections inspector button is in the inspector selector bar, and it looks like this: image: ../Art/connections_inspector_button.jpg

In the Connections inspector, Xcode displays the connections for the selected object (in this case, the app delegate). In your workspace window, you should see something like this:

image: ../Art/26_inspectconnections.png

Notice the five connections (three actions and two outlets) you created to the app delegate. Since the text field and vertical slider use the same takeFloatValueForVolumeFrom: action method they are grouped together under Received Actions. Also notice that there’s a connection between the app delegate and its window and the app delegate and the File’s Owner. Xcode provides these default connections for your convenience; you do not have to use them in any way.

Test the App

If you run your app now, it behaves the same as the last time you tested it after you first added the UI elements to the window. The connections between the objects exist but because the action methods do nothing, there is no new behavior to observe. So that you can test and better understand the connections you made, in the implementation file, AppDelegate.m, add log statements to the action methods.

bullet
To add log statements to the action methods
  1. Display the implementation file in the source editor by selecting AppDelegate.m in the navigator area in the left pane.

  2. Add a single NSLog statement to the mute: method to indicate that the method has been invoked.

    - (IBAction)mute:(id)sender {
        NSLog(@"received a mute: message");
    }
  3. Implement the takeFloatValueForVolumeFrom: method as follows:

    - (IBAction)takeFloatValueForVolumeFrom:(id)sender {
        NSString *senderName = nil;
        if (sender == self.textField) {
            senderName = @"textField";
        }
        else {
            senderName = @"slider";
        }
        NSLog(@"%@ sent takeFloatValueForVolumeFrom: with value %1.2f", senderName, [sender floatValue]);
    }

    The method checks which control was the sender and logs a message indicating both the sender and its current float value. The NSLog function logs a string using the format specified by the format string. (This is very similar to the C printf function.) The string %@ indicates that a string object should be substituted.

    The method combines two fairly common patterns in Cocoa: determining the sender of a message and sending a message back to it. In this case, it’s not necessary to know which object sent the message—all that’s needed is its float value—but it serves to illustrate the point.

When you test the app, show the console so that you can see the log messages.

bullet
To test the app
  1. Click the Run button in the toolbar to build and run the project.

    If a dialog appears asking whether to stop running TrackMix, click Stop.

  2. If necessary, in the Xcode toolbar, click the debug area button to show the debug area.

    The debug area button is the middle View control and it looks like this: image: ../Art/debug_area_button.jpg

  3. Click the rightmost button in the debug area view toolbar next to the Clear button to display the console.

    image: ../Art/27b_consolebutton.pngimage: ../Art/27b_consolebutton.png
  4. Make sure that Target Output is selected from the console pop-up menu.

    image: ../Art/27_consolesettings.png
  5. In TrackMix, enter a numeric value in the text field and press Return, move the slider, and click the Mute button.

    As you interact with these UI elements, you should see appropriate messages in the console.

Recap

You created connections between the UI elements and the app delegate object by Control-dragging from the UI element to a AppDelegate class source file and configuring the action or outlet. This operation performed two tasks: It created the connection between the objects and added the necessary code for the action or outlet to the source files.

You don’t have to use the Xcode feature that automatically adds code when you establish a connection by Control-dragging from the canvas to a source file. Instead, you can add the property and method declarations to the source files yourself and then make the connections from the UI elements directly to the App Delegate object in the editor area. Typically, though, you make fewer mistakes (and have less typing to do) when you let Xcode do as much of the work as it can.

Currently, the user interface is not synchronized (that is, the text field and slider may have different values). In the next chapter, you’ll implement the Track class to separate the model data from the UI elements and in the following chapter implement the action methods.