Challenge: Saving and Loading - My Solution


Here’s my crack at this Challenge. Would love to hear any feedback on where I could’ve done things better/smarter.

I started by modifying initWithCoder: in TouchDrawView.m to the following:

[code]- (id) initWithCoder:(NSCoder *)c
self = [super initWithCoder:c];

if (self) {
    linesInProcess = [[NSMutableDictionary alloc]init];
    if (!completeLines) {
        NSString *path = [self lineArchivePath];
        completeLines = [[NSKeyedUnarchiver unarchiveObjectWithFile:path]retain];
    if (!completeLines){
        completeLines = [[NSMutableArray alloc]init];
    [self setMultipleTouchEnabled:YES];

[self setTag:66];
return self;


Wondering what’s up with the [self setTag:66] call?

I knew I needed the app delegate to initiate the save when applicationDidEnterBackground was called but I couldn’t figure out the best way of getting a reference to my TouchDrawView object from inside the app delegate. I found the setTag: method and decided to use it since it seemed simplest. Other options would have been to store a pointer to the TouchDrawView object as an ivar in the app delegate object but that seemed kludgey. I thought the app delegate had access to the root view and that I could find it that way, somehow, but I couldn’t find the details on how to make that work (if it’s even possible).

Inside my app delegate I modified applicationDidEnterBackground:

- (void)applicationDidEnterBackground:(UIApplication *)application
    TouchDrawView *myTouchDrawView = (TouchDrawView*)[self.window viewWithTag:66];
    [myTouchDrawView saveChanges];

I added a lineArchivePath method to TouchDrawView.m that simply borrows the code from Whereami to handle the path creation:

-(NSString *)lineArchivePath
    return pathInDocumentDirectory(@"");

The method above gets called from a saveChanges: method I added to TouchDrawView:

    //returns success or failure
    return [NSKeyedArchiver archiveRootObject:completeLines toFile:[self lineArchivePath]];

Lastly I made Line conform to NSCoding protocol and implemented the two encode/decode methods from said protocol:

- (id)initWithCoder:(NSCoder *)decoder
    self = [super init];
        // Our CGPoints are archived as NSValues. We need to create CGPoints and somehow get the data out of NSValue objects and into CGPoints.

        NSValue *vBegin = [[NSValue alloc]init];
        NSValue *vEnd = [[NSValue alloc]init];
        vBegin = [decoder decodeObjectForKey:@"begin"];
        begin = [vBegin CGPointValue];
        vEnd = [decoder decodeObjectForKey:@"end"];
        end = [vEnd CGPointValue];
    return self;

- (void)encodeWithCoder:(NSCoder *)encoder
    NSValue *vBegin = [NSValue valueWithCGPoint:begin];
    NSValue *vEnd = [NSValue valueWithCGPoint:end];
    [encoder encodeObject:vBegin forKey:@"begin"];
    [encoder encodeObject:vEnd forKey:@"end"];

Again - any comments on things I missed or where/how I could optimize this are welcome and encouraged.