Documentation Archive Developer
Search

Implementing Action Methods

The app delegate’s action methods need to synchronize the audio track volume that the user sets in one UI element with the values displayed by other UI elements. When the user clicks the Mute button, the track volume displayed by the text field and slider should be set to zero. Similarly, if the user enters a volume in the text field or moves the slider, the other UI element needs to reflect this change. In the Model-View-Controller design pattern, it’s the responsibility of the controller (that is, the app delegate) to implement this behavior.

image: ../Art/TrackMixUpdateUI.png

Implement the takeFloatValueForVolumeFrom: Method

The text field and slider both send a takeFloatValueForVolumeFrom: message to the app delegate. But the method doesn’t update the track volume or the other UI elements yet.

bullet
To implement the takeFloatValueForVolumeFrom: method
  • In the AppDelegate.m file, change the implementation of the takeFloatValueForVolumeFrom: method as follows:

    - (IBAction)takeFloatValueForVolumeFrom:(id)sender {
        float newValue = [sender floatValue];
        [self.track setVolume:newValue];
        [self updateUserInterface];
    }

There are several pieces to this method:

Notice that Xcode shows an error icon for the [self updateUserInterface]; statement. It does this because you haven’t declared or implemented the updateUserInterface method yet. You’ll do both next.

image: ../Art/27c_compilererror.png

Implement the updateUserInterface Method

The information shown in the user interface needs to be kept synchronized with what is stored in the model. In this app, the volume level is shown in two places. It might be tempting to let one of them update the other directly, but doing so tends to be difficult to maintain and debug. The best way to keep the user interface consistent is to always use the value in the model object as the true value and synchronize everything in the user interface against it. In this implementation, you use the text field and slider outlets you created earlier.

bullet
To synchronize the user interface
  1. In the AppDelegate.h file, declare the updateUserInterface method as follows:

    - (void)updateUserInterface;
  2. In the AppDelegate.m file, just before the @end statement, implement the updateUserInterface method as follows:

    - (void)updateUserInterface {
     
        float volume = [self.track volume];
        [self.textField setFloatValue:volume];
        [self.slider setFloatValue:volume];
    }

    The method first retrieves the track’s volume, then sets that as the float value of both the text field and the slider.

  3. Run the app.

    The app should behave as you expect. Moving the slider should update the value shown in the text field, and typing a new value in the text field (and clicking Return) should update the slider.

The next task is to implement the action method for the button.

Implement the mute: Method

The implementation of the mute: method follows the same pattern as the takeFloatValueForVolumeFrom: method, except that the track’s volume is set to zero.

bullet
To implement and test the mute: method
  1. In the AppDelegate.m file, change the implementation of the mute: method as follows:

    - (IBAction)mute:(id)sender {
        [self.track setVolume:0.0];
        [self updateUserInterface];
    }
  2. Run the app.

    Pressing the Mute button should now set the track volume, text field, and slider values to zero.

Although the app appears to be working correctly now, there is one subtle bug. In setting up the nib file, you entered starting values for the text field and slider (both were set to 5). When the app starts, however, the track is created and its volume is set to zero. You need to ensure that the user interface and model values are properly synchronized at launch.

Make the User Interface Consistent at Launch

To ensure that the user interface is consistent with the model values at launch, you can invoke the updateUserInterface method after creating the track object.

bullet
To ensure that the app is consistent at launch
  1. In the AppDelegate.m file, update the applicationDidFinishLaunching: method to invoke updateUserInterface after setting the track property.

    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
        Track *aTrack = [[Track alloc] init];
        [self setTrack:aTrack];
        [self updateUserInterface];
    }
  2. Run the app.

    The app should generally behave as it did before, except that when it launches it displays a value of 0 rather than 5.

Recap

You implemented the methods of the app delegate that provide the app’s core functionality—updating multiple views when the model data changes.

The next task is to look more closely at how the app behaves to see whether the user experience might be improved.