Model objects contain special knowledge and expertise. They hold data and define the logic that manipulates that data. For example, a customer object, common in business applications, is a model object. In Currency Converter, the model class you’re going to create is the converter class. In the MVC design pattern, instances of a model class do not communicate directly with the user interface.
In this chapter, you will create the model for your application. First, you will learn how to create a new class in Xcode. Then, you will define the interface for your model before implementing it. Finally, you will implement the entire functionality of the class. In the process, you will learn some of the syntax of Objective-C, including how to declare variables and methods. You will also be introduced to the concept of declared properties—a feature in Objective-C 2.0 that makes writing accessor methods incredibly quick and simple.
Specify the Model Class
Declare the Model Interface
Implementing the Model
What’s Next?
Select the Classes group in the Groups & Files list.
Choose File > New File.
Choose to create a new Objective-C Class and name it Converter.
In Xcode, select both Converter.h and Converter.m by holding down command and clicking on each.
Click-and-drag both files into the Classes group in the Groups & Files list.
Note: Organizing your project files in the various groups in the Groups & Files list is simply good practice. The default location for all .h and .m files is the Other Sources group in the Groups & Files list. It is a good idea to separate classes from non-classes (like main.m), especially in larger projects. However, the organization of your project makes no difference to the compiler.
The model for the Currency Converter is a simple class that encapsulates two variables: the amount in US dollars and the exchange rate. The model’s job is to multiply these two numbers and return the result. This means the model needs:
One class: Converter
Two variables of type float: sourceCurrencyAmount and rate
One method: (float)convertCurrency
The two variables are defined between the braces of the converter class. Define the variables:
If Converter.h is not already open for editing, double-click Converter.h in the Classes group of the Groups & Files menu. This opens the file in an editor window.
Insert the highlighted line in Listing 3-1 into Converter.h
Listing 3-1 Declaration of the member variables in Converter.h
#import <Cocoa/Cocoa.h> |
@interface Converter : NSObject { |
float sourceCurrencyAmount, rate; |
} |
Objects encapsulate data, as explained in “Classes and Objects.” The scope of variables in an object is limited to that particular object—that is, the instance of that class. One instance of a customer class, for example, can only see its own data, not the data of any customer object. But say a specific customer needs to compare itself with another customer. In order for this to be possible, classes supply accessor methods to read and write to the data an object encapsulates. This gives the classes the discretion of what data they wish to share. For example, if a specific class does not want to share certain variables it encapsulates with another class, and only wants to use them for internal use, it can simply not have accessor methods for that variable. This is also true if a class wants external entities to have read-only access to its variables. In that case, a class will have methods that get values, but no methods that set values.
Objective-C 2.0 provides a feature called declared properties. A property declaration is, effectively, a shorthand for declaring the setter and getter for an attribute of an instance of a class. In addition to the declaration itself, there are directives to instruct the compiler to synthesize the accessors and to inform the compiler that you will provide the methods yourself at runtime. There are two parts to a property, its declaration and its implementation.
You declare a property as follows:
@property(attributes) Type variableNameList;
where attributes is a comma-separated list of keywords such as readwrite and copy, for example:
@property(copy) NSString *name;
For the purposes of Currency Converter, add the following line after the closing brace of the converter class in Converter.h:
@property(readwrite) float sourceCurrencyAmount, rate; |
At compile time, the compiler treats this as if you had declared the following methods:
- (float)sourceCurrencyAmount; |
- (void)setSourceCurrencyAmount:(float)newSourceCurrencyAmount; |
- (float)rate; |
- (void)setRate:(float)newRate; |
Note: Objective-C 2.0 features are not compatible with a system running any operating system prior to Mac OS X 10.5. If you are on Mac OS X 10.4 or below, you must declare these methods manually.
There is currently no implementation for these methods. In the next section, you will implement the methods.
The one method the model requires is a simple function to multiply two the two values encapsulated by the converter class.
Add the following line as the next line of code in Converter.h:
- (float)convertCurrency; |
Although this method takes no arguments, it multiplies two values that are not passed to the method, nor are they instantiated in the method. This is possible because the method is part of the converter class, and it has access to the converter class’s member variables. It gets to treat those variables as if they were already defined as local variables. It is common practice to use accessor methods even when the variable is in scope, but for this application you will access them using the command self.variableName (where self is a keyword that is a pointer to the current instance of the object). In the next section, you will define the behavior of the converter and get to see how this works.
Now it’s time to define the behavior of the functions you declared in Converter.h.
In the Classes group of the Groups & Files menu, double-click Converter.m to open the file for editing.
Create the getters and setters for the two member variables—sourceCurrencyAmount and rate.
Remember you used @property to create the prototypes for the getter and setter methods in Converter.h. If you provide a getter and setter (or just a getter in the case of a read-only property) method implementation for a property, you don’t need to do anything more. Commonly, however, you use the @synthesize directive in @implementation blocks to trigger the compiler to generate accessor methods for you.
Add the following line into Converter.m after the @implementation Converter line:
@synthesize sourceCurrencyAmount, rate; |
This line defines the body of the getter and setter methods for the variables sourceCurrencyAmount and rate based on the properties you set in the Converter.h file.
Note: For more information on properties and the various options available, read “Properties” in The Objective-C 2.0 Programming Language.
Insert the highlighted lines in Listing 3-2 into Converter.m.
Listing 3-2 Definition of the convertCurrency method in Converter.m
#import "Converter.h" |
@implementation Converter |
@synthesize sourceCurrencyAmount, rate; |
- (float)convertCurrency { |
return self.sourceCurrencyAmount * self.rate; |
} |
@end |
The convertCurrency method multiplies the values of the converter class’s two member variables and returns the result.
You just defined and implemented the basic functionality of your application by creating the model. In the next chapter, you will create the view, which is the user interface for the application.
© 2007 Apple Inc. All Rights Reserved. (Last updated: 2007-10-31)