In this app, there are two custom classes that contain application logic. The Xcode template provided anAppDelegate class and created an instance of it in the nib file for you. When you made connections between the UI elements and the app delegate, you added custom code to the AppDelegate class. The app delegate acts as a controller object in the Model-View-Controller design pattern by updating views and managing model objects that store the actual application data. You now need to implement the model object that stores the track’s volume. You need to implement a Track class and create an instance of it in the app delegate. When a UI element changes a value, the app delegate is responsible for updating the track’s volume and synchronizing the views.

这个应用中,有2个自定义类包含了应用程序逻辑(application logic)。Xcode 模板提供了一个 AppDelegate 类, 并在nib 文件里为你创建了一个它的实例。 当你给UI元素和应用代理(app delegate)之间做连接时,你向AppDelegate类添加了自定义代码。应用代理(app delegate)在 Model-View-Controller 模型-视图-控制器 设计模式 就相当于 一个控制器(controller)对象的角色,它更新(views)那些视图并管理那些存储着真实应用数据的模型对象(model objects)。现在你需要实现那些存储着轨道音量(track's volume)的模型对象。你需要实现一个 Track类,并在app delegate里创建一个实例对象。当一个UI元素的值发生改变,应用代理(app delegate) 负责更新这个音轨音量(track's volume),让视图同步。

image: ../Art/TrackMixMVC.png

Create Header and Implementation Files for the Track Class

为Track类创建头文件 和 实现文件。

The first task is to create header and implementation files for the new Track class. It will inherit from theNSObject class, the root class in Objective-C.

首先,我们需要为Track类创建头文件和实现文件。它继承自Objective-C的基类NSObject类。

一、To create the files for the new class
  为新类创建文件。
  1. In Xcode, in the project navigator select the TrackMix group folder.

    在Xcode中,在项目导航栏里选择TrackMix 组文件夹。

    When you add new files in the next steps, they are added to the project navigator under this selection.

    当你接下来添加新文件时,它们会被加到这个文件夹下面。

  2. Create an Objective-C class as follows:

    创建一个Objective-C类,如下:

    • Choose File > New > File.(选择 File > New > File)

    • In the template dialog, select Cocoa in the OS X section. (在模板对话框,在 OS X 选区 选择 Cocoa)

    • Select the Objective-C class template and click Next. (选择 Objective-C类模板,然后点击“Next”)

    image: ../Art/28_createnewclass.png
  3. In the screen that appears, set the class’s name to Track (by convention, class names begin with an upper case letter). Leave the new class as a subclass of the NSObject class, and click Next.

    在出现的窗口上,设置类名为:Track (按照惯例,类名以一个大写字母开头)。Subclass of 字段,设置为NSObject, 让新类成为NSObject类的子类, 然后点击“Next”。

    image: ../Art/29_createnewclass2.png
  4. In the Save dialog, leave the group and targets as they are, and click Create.

    在保存对话框中,保持Group和Targets字段不变,点击“Create”。

The files should now be located in your project’s TrackMix group folder. If you look at the files, you’ll see that stub class interface and implementation declarations are provided for you. You need to add an attribute to represent the volume.

现在新文件应该已经位于项目中TrackMix组文件夹下。如果你查看这些文件,你将看到为你提供的存根类接口(stub class interface)和实现声明(implementation declarations). 你需要添加了一个属性来表示音量。

Implement the Track Class

实现Track类

The track’s volume attribute is implemented using an Objective-C declared property. A declared property is a convenient way to implement an instance variable.

属性 音轨音量(track's volume) 是用一个Objective-C 声明的属性(declared property)来实现的。一个 声明的属性(declared property)是实现一个实例变量的便利方法。

一、To add a volume property
  添加音量属性
  • In the Track header file (Track.h), add a property declaration for a float value called volume.

    在头文件(Track.h)里,为一个float值添加一个属性声明,我们称这个float值为音量。 如下图:

    The header file should look like this:

    #import <Foundation/Foundation.h>
     
    @interface Track : NSObject
    @property (assign) float volume;
    @end

When you build your app, the compiler reads the property declaration and generates a private instance variable and accessor methods for the volume property. The value of the _volume instance variable is automatically set to 0 when the Track object is created.

当你构建应用时,编译器(compiler)读取属性声明,为volume属性生成私有实例变量和存取方法。当Track对象创建时,_volume实例自动被初始化为0。

Add a Track Property

添加一个Track 属性

For the app delegate to use an instance of Track—to store the volume displayed by multiple UI elements—you add a track property to the AppDelegate class.

为了让应用代理(app delegate)能够使用一个Track实例--用来存储多个UI元素显示的音量--你需要给AppDelegate类添加一个track属性。

The compiler will generate an error, though, if you declare a property without telling it about the Track class. You could import the header file for the Track class (Track.h), but typically you provide a forward declaration using @class. A forward declaration is a promise to the compiler that Track will be defined somewhere else and that it needn’t waste time checking for it now. (Doing this also avoids circularities if two classes need to refer to each other and would otherwise include each other’s header files.) You then import the header file itself in the implementation file.

不过,如果你不告诉编译器有关Track类就声明一个属性,编译器会生成一个错误(error). 你可以导入头文件(Track.h),但是通常你只要用@class提供一个向前声明(forward declaration,这样实现文件自己就会导入头文件。一个向前声明(forward declaration)是告诉编译器:Track 类会在别的地方声明,现在不需要浪费时间去检查。(当2个类需要互相引用时,这样做还避免了发生死锁(circularities),否则就得包含对方的头文件)

一、To add a track property to app delegate
  给应用代理(app delegate)添加一个 track 属性。
  1. In the app delegate’s header file (AppDelegate.h), add a forward declaration for the Track class before the interface declaration for AppDelegate.

    在应用代理(app delegate)的头文件(AppDelegate.h)里,在AppDelegate接口声明之前 为Track 类 添加一个向前声明。

    @class Track;
  2. Add a declaration for the track property between the last @property declaration and the @end symbol.

    在头文件中最后一个@property声明和@end符号之间,添加一个track属性声明。

    @property (strong) Track *track;

    The property specifies the strong attribute rather than the weak attribute, indicating that the Trackobject is owned by the app delegate. As long as the app delegate references it, the Track object won’t go away. The outlet property declarations you created earlier use the weak attribute because the corresponding UI elements are contained in the view hierarchy that is owned by the window, not the app delegate. The window and its view hierarchy can go away independent of the app delegate.

    property属性指定了一个strong属性,而不是weak属性,表明Track对象被应用代理(app delegate)所拥有。只要app delegate引用它,Track 对象就不会消失。你在之前创建的接口属性声明(outlet property declarations)中使用weak,是因为相应的UI元素包含在视图层中,是窗口拥有的,而不是app delegate拥有的。窗口和它的视图层独立于app delegate 可以消失。

tip icon

Tip Objective-C is case sensitive. Track refers to a class and track is a property of the Track class. A common programming error in Cocoa is to misspell a symbol name, frequently by using a letter of an inappropriate case (for example, “tableview” instead of “tableView”). This tutorial deliberately uses Trackand track to encourage you to look at the name carefully. When writing code, make sure you use the appropriate symbol.

 Tip(提示): Objective-C 是区分大小写的。Track 是指一个类,而track 是Track 类的一个属性。在Cocoa中,一个常见的编程错误是一个符号名的拼写错误, 常常是因为使用不合适的大小写格式。(比如:用"tableview" 代替 "tableView")。教程中故意使用 Track  和 track 就是为了鼓励你仔细看名字。当你写代码时,确保使用正确的符号。

 

Confirm that your AppDelegate class interface file (AppDelegate.h) looks like this. (The comments are not shown and the order of property and method declarations is not important.):

确认你的AppDelegate类接口文件(AppDelegate.h)看起来像这样。(注释没有显示,属性和方法声明顺序不重要。)

#import <Cocoa/Cocoa.h>
 
@class Track;
 
@interface AppDelegate : NSObject <NSApplicationDelegate>
 
@property (assign) IBOutlet NSWindow *window;
@property (weak) IBOutlet NSTextField *textField;
@property (weak) IBOutlet NSSlider *slider;
@property (strong) Track *track;
 
- (IBAction)mute:(id)sender;
- (IBAction)takeFloatValueForVolumeFrom:(id)sender;
 
@end

Create the Track Instance

创建 Track 实例

Now that you’ve added the track property to the AppDelegate class, you need to set its value to an instance ofTrack.

现在你已经添加了 track 属性 到 AppDelegate类, 你需要设置它的值为一个Track实例。

一、To create an instance of the Track class
  1. In the implementation file for the app delegate (AppDelegate.m), import Track.h by adding this line of code before the @implementation statement:

    在应用程序代理(app delegate)实现文件(AppDelegate.m)里,导入(import)Track.h. 在@implementation语句前面添加下面代码行:

    #import "Track.h"

    Otherwise, you’ll see a compile error later when you reference the Track class.

    否则,当你引用 Track 类的时候就会出现一个编译错误(compile error)。

  2. Create an instance of Track by adding the following code as the first two statements in the implementation of the applicationDidFinishLaunching: method:

    在applicationDidFinishLaunching: 方法实现开始处,加入以下2条语句,给Track类创建一个实例:

    Track *aTrack = [[Track alloc] init];
    [self setTrack:aTrack];

These two lines of code do the following:

这2条语句做了以下事情:

  • Allocate memory for an instance of the Track class.

    Track 类实例分配内存。

  • Initialize the instance of the Track class to prepare it for use.

    初始化Track类的实例。

  • Set the new track to be the track property using an accessor method.

    用存取方法(accessor method)给track属性,设置了一个新轨道(track)。

    You don’t need to declare or write the code for setTrack:. The compiler automatically creates this accessor for the track declared property that hides the _track private instance variable.

    你不需要声明或写setTrack: 代码。 编译器自动会在隐藏的_track 私有实例变量里的track属性创建存取方法(accessor)。

Objective-C also supports dot notation. You can replace [self setTrack:aTrack]; with:

Objective-C 也支持点运算符(dot notation)。 你可以把[self setTrack:aTrack]替换为下面语句:

self.track = aTrack;

The dot notation invokes exactly the same accessor method (setTrack:) as in the original implementation. The dot notation provides a compact syntax for invoking accessor methods—especially when you use nested expressions.

点运算符的作用跟在最初实现(original implementation)里的(setTrack:)存取方法完全一样。点运算符提供了一个调用存取方法的简洁方法,尤其是你使用嵌套表达式(nested expressions)时。

Memory management: You have created several objects, but you never explicitly deallocated any of them. Don’t worry, you haven’t been creating memory leaks; you’ve been using ARC. Automatic Reference Counting (ARC) is a compiler feature that uses the Cocoa naming conventions for methods to automatically insert memory management code at compile time. ARC is enabled by default when you create a new project in Xcode.

 内存管理:你创建了几个对象,但是你从来没有明确地释放它们。别担心,你不一定要创建内存池;你已经使用了ARC。自动引用计数器(Automactic Reference Counting--ARC)是一个编译器功能 --- 在编译时,那些方法使用Cocoa 命名约定自动插入内存管理代码。当你在Xcode创建一个新项目后,ARC默认启动。

Test the App

You can now test your app.

测试应用。

一、To test the app
  • Compile and run the project (choose Build > Build and Run, or click the Run button in Xcode’s toolbar).

    编译运行项目(选择 Build > Build and Run, 或点击在Xcode 工具栏上点击Run按钮)

Your app should compile without errors, and you should see the same user interface as before. Disappointingly, the user interface should also behave as it did before. Although you now have a Track object, the app delegate doesn’t do anything with it beyond creating it. There is a little more work to do to complete the implementation.

你的应用应该不会出现错误, 你应该看到跟之前一样的用户界面。令人失望的是,用户界面的行为也跟之前一样。尽管你现在已有一个Track对象, 应用代理(app delegate)除了创建它,不会做任何其它事情。 现在我们还需要多做些工作才能完成该实现。

Recap(概括)

You implemented a model class called Track to store a volume attribute displayed by multiple UI elements. In the app delegate, you declared a property for a Track object and performed a few other housekeeping tasks. Accessor methods for the property are automatically synthesized.

你实现了一个叫Track的模型类,用来存储一个由多个UI元素显示的音量属性(volume attribute)。在应用代理(app delegate)中,你给一个Track对象声明了一个特性(property), 进行了一些其它日常事务。 特性(property)的存取方法(accessor methods)是自动实现的。

 

posted on 2013-06-01 10:43  cainiaozhang  阅读(476)  评论(0编辑  收藏  举报