Wednesday, October 14, 2009

Instant Cocoa: Checkbook project 2


Data model objects


As I mentioned, the individual transactions in the checkbook are represented by instances of a class, CheckbookItem. This is so we can register with the class to be informed when the user changes something.

To use a class in this way, there is really no code needed. We just use @property and @synthesize as usual. Because it's a class object rather than an array of strings and numbers, we can't just do [array writeToFile:fn atomically:YES]. Instead, we'll use an NSData object to "freeze-dry" our array of objects.

To do this, we need to teach the class how to encode itself using two required methods:

- (void)encodeWithCoder:(NSCoder *)coder
- (id)initWithCoder:(NSCoder *)coder


We feed the encoder things it knows how to encode, along with a key to remember them by. When we load the data from a file, we use the same keys to get the objects back.

Here is the interface and implementation for CheckbookItem:


#import <Cocoa/Cocoa.h>

@interface CheckbookItem : NSObject
<NSCoding>{

}

@property (retain) NSString *name;
@property (retain) NSNumber *amount;
@property (retain) NSNumber *isDeposit;
@property (retain) NSString *checkNumber;
@property (retain) NSNumber *clear;
@property (retain) NSNumber *balance;
@property (retain) NSDate *date;

- (NSString *)description;

- (id)initWithCoder:(NSCoder *)coder;
- (void)encodeWithCoder:(NSCoder *)coder;

@end

#import "CheckbookItem.h"

@implementation CheckbookItem

@synthesize name;
@synthesize amount;
@synthesize isDeposit;
@synthesize checkNumber;
@synthesize clear;
@synthesize balance;
@synthesize date;

- (NSString *)description { return name; }

// we don't bother to save balance
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:name forKey:@"name"];
[coder encodeObject:amount forKey:@"amount"];
[coder encodeObject:isDeposit forKey:@"isDeposit"];
[coder encodeObject:checkNumber forKey:@"checkNumber"];
[coder encodeObject:clear forKey:@"clear"];
[coder encodeObject:date forKey:@"date"];
}

- (id)initWithCoder:(NSCoder *)coder {
name = [[coder decodeObjectForKey:@"name"] retain];
amount = [[coder decodeObjectForKey:@"amount"] retain];
isDeposit = [[coder decodeObjectForKey:@"isDeposit"] retain];
checkNumber = [[coder decodeObjectForKey:@"checkNumber"] retain];
clear = [[coder decodeObjectForKey:@"clear"] retain];
date = [[coder decodeObjectForKey:@"date"] retain];
return self;
}

@end