Bronze Solution #1


#1

For my first run at the Bronze Challenge, I decided to add just the necessary elements to provide Archiving. Thus, I did not introduce a LineStore. My rationale is that I wanted to get the archiving working. However, I am going to repeat this exercise using a LineStore. I will also attempt this using CoreData for my third attempt. I really want to understand both of these techniques so I will implement both in a series of solutions.

General Explanantion
Starting with Line.h I simply added the NSCoding Protocol. In TouchDrawView I added two methods for finding the archive path and then the BOOL save method. I also added the ability to unarchive the data if it exists in the initWithFrame: method.The final piece of the puzzle, which was the hardest for me, was trying to call the saveLines: method from the AppDelegate. I kept trying something like [TouchDrawView saveLines]. But all I got was a no class method error. I finally got it that this error was telling me it required a +(BOOL)saveLines class method which I did not want to/could not implement. So I finally figured out that what I needed was a reference to the instance of the TouchDrawView. To do this I created an instance variable of the TouchDrawView view when the controller created it. I then needed an instance variable of the controller in the AppDelegate to get the view.

Feel free to comment on what I have done.

Line.h

@interface Line : NSObject <NSCoding>

Line.m

@implementation Line

-(void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeCGPoint:[self begin] forKey:@"begin"];
    [aCoder encodeCGPoint:[self end]   forKey:@"end"];
}

-(id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];
    
    if (self)
    {
        [self setBegin:[aDecoder decodeCGPointForKey:@"begin"]];
        [self setEnd:[aDecoder decodeCGPointForKey:@"end"]];
    }
    
    return self;
}

@end

TouchDrawView.h

-(NSString *)lineArchivePath;
-(BOOL)saveLines;

TouchDrawView.m

-(id)initWithFrame:(CGRect)r
{
    self = [super initWithFrame:r];
    
    if (self)
    {
        linesInProcess = [[NSMutableDictionary alloc] init];

        // Load lines from the archive
        NSString *path = [self lineArchivePath];
        completeLines = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
        
        if (!completeLines)
        {
            completeLines = [[NSMutableArray alloc] init];
        }
        
        [self setBackgroundColor:[UIColor whiteColor]];
        [self setMultipleTouchEnabled:YES];
    }
    
    return self;
}
-(NSString *)lineArchivePath
{
    NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString * documentDirectory = [documentDirectories objectAtIndex:0];
    
    return [documentDirectory stringByAppendingPathComponent:@"lines.archive"];
}

-(BOOL)saveLines
{
    NSString *savePath = [self lineArchivePath];
        
    return [NSKeyedArchiver archiveRootObject:completeLines toFile];
}

TouchViewController.h

@interface TouchViewController : UIViewController
{
    TouchDrawView *tvView;
}

-(TouchDrawView *) tvView;

@end

TouchViewController.m

-(void)loadView
{
    tvView = [[TouchDrawView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    [self setView:tvView];
    
    //CGRectZero
}

-(TouchDrawView *)tvView
{
    if (tvView)
    {
        return tvView;
    }
    return [[TouchDrawView alloc] initWithFrame:CGRectZero];
}

AppDelegate.m

@implementation AppDelegate
{
    TouchViewController *tvc;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    
    tvc = [[TouchViewController alloc] init];
    [[self window] setRootViewController:tvc];
    
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}


- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    
    //Archive the line data
    TouchDrawView *tvView = [tvc tvView];
    BOOL success = [tvView saveLines];
    
    if (success)
    {
        NSLog(@"Lines were saved");
    }
    else
    {
        NSLog(@"Lines were NOT saved");
    }   
}