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.

应用代理(app delegate)的动作代理需要让 音频轨道音量(autio track volume) 跟用户在一个UI元素(UI element)里设置的值和别的UI元素显示的值保持同步。当用户点击 Mute按钮, 文本框 和 滑动条显示的值应被设置为0。同样的,如果用户在文本框里输入了一个音量值,其它UI元素也应该反应出这个改变。在Model-View-Controller 设计模式里,控制器(就是,app delegate) 来负责实现这个行为。

image: ../Art/TrackMixUpdateUI.png

Implement the takeFloatValueForVolumeFrom: Method、

实现 takeFloatValueForVolumeFrom: 方法

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.

文本框和滑动条都向 应用代理(app delegate) 发送 takeFloatValueForVolumeFrom: 消息。 但是方法还不能更新轨道音量(track volume) 或 其它UI元素。

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

    在AppDelegate.m 文件里,把方法 takeFloatValueVolumeFrom: 的实现代码换成如下代码:

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

There are several pieces to this method:

该方法有几个步骤:

  • float newValue = [sender floatValue];

    This line retrieves the sender’s float value and stores it in a local variable. The sender is the text field or slider that sent this message.

    本行检索(retrieves)发送者(sender)的float值, 并把它存入一个本地变量。 sender(发送者)是发送该消息的(message)的文本框或滑动条。

  • [self.track setVolume:newValue];

    This line sets the track’s volume to the new value.

    本行把属性track的值设为新值。

  • [self updateUserInterface];

    This line invokes a new method to ensure that the user interface is consistent with the value of the track’s volume.

    改行调用了一个新方法,用来确保用户界面显示的值跟track的值保持一致。

    The method doesn’t exist yet. You could put the code here, but similar functionality will be required in the mute: method; placing the code in its own method means you need write it only once.

    该方法还不存在。 你可以先把代码放这里,但是在方法mute: 里也要求相似的功能;把代码放在它自己的方法里,意味着你只需要写一次代码。避免代码重复。

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.

请注意, Xcode 在[self updateUserInterface] 行显示了一个错误图标。这是因为你还没有声明或实现 updateUserInterface方法。你将在接下来完成这些。

image: ../Art/27c_compilererror.png

Implement the updateUserInterface Method

实现 updateUserInterface 方法

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.

用户界面(user interface)上显示的信息应该跟 模型(model)里存储的保持同步。 教程中,有2个地方显示音量值(volume level)。 让它们其中一个直接更新另一个可能很有诱惑力,但是这样做往往难以维护(maintain)和调试(debug)。 保持用户界面一致性的最好方法是坚持使用模型对象中的值作为真确值,并用它让用户界面同步。在这实现中,你需要使用之前创建的文本框和滑动条。

一、To synchronize the user interface
  同步用户界面
  1. In the AppDelegate.h file, declare the updateUserInterface method as follows:

    在AppDelegate.h文件里,声明 updateUserInterface 方法:

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

    在AppDelegate.m 文件 @end 语句前面,实现 updateUserInterface 方法:

    - (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.

    该方法首先检索 track的值,然后给文本框和滑动条设置该值。

  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.

    应用程序应该已经能像你预期的那样工作了。 移动滑动条能同时更新文本框中的值,往文本框中输入一个新值(按回车(Return)),也可以更新滑动条。

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.

mute: 方法的实现 跟 takeFloatValueForVolumeFrom: 方法类似,除了track的值被设为0。

一、To implement and test the mute: method
  实现 并 测试 mute: 方法
  1. In the AppDelegate.m file, change the implementation of the mute: method as follows:

    在AppDelegate.m 文件, 改变mute:方法的实现代码:

    - (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.

    现在点击 Mute 按钮,文本框和滑动条的值被设置为0。

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.

尽管现在应用程序看起来能正常工作, 但是这里有一个细小的错误(subtle bug)。 在你建立nib文件时,文本框和滑动条的初始值都被设置为5. 但是当应用程序(app)启动时,track属性被创建,它的值被初始化为0。你应该确保用户界面和模型对象的值在启动时(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 theupdateUserInterface method after creating the track object.

为了确保用户界面和模型值在启动时就保持一致,你可以在创建完track对象后就调用方法:updateUserInterface 。

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

    在AppDelegate.m文件,更新 applicationDidFinishLaunching: 方法,使它在设置完track属性后调用 updateUserInterface。

    - (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.

    应用程序应该跟之前一样工作,除了当它启动时它显示的值是0而不是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.

你实现了应用代理(app delegate)的方法,给应用程序提供了核心功能(core functionality)---当模型数据(model data)发生变化时,更新多个视图(views)。

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

下个任务是更密切地关注应用程序的行为,看看能否改进用户体验。

 

posted on 2013-06-02 16:01  cainiaozhang  阅读(241)  评论(0编辑  收藏  举报