How to Archive Your Object Graph

Matthew Campbell, April 26, 2012

Your app’s object graph is the collection of objects that are active in your app when the app is running.  For iOS apps, this is the application object, the app delegate, window and all the custom objects that you’ve created.

Usually, your application will have a sub-set of objects in your object graph that you are using to store user generated content.  For Tasting Notes, this was a Notebook object that was made up of Note objects.

This is the part of the object graph that you probably have managed by Core Data or saved locally to your app’s filesystem in one way or another. This is also the part of the object graph that you might want your users to be able to save or backup.

Archive It!

This is where object archiving comes into play. In Objective-C you can archive your object’s state and store the content in a file. This file can be sent to another app, stored or transmitted in some way.

To make this work is a lot simpler than you would think at first glance. All you need to do is have the class that you want to archive adopt the NSCoding protocol and then implement two methods that the class must know to do archiving. Then you may use the NSKeyArchiver class to save the contents of those objects to the filesystem of your Mac or iOS app.

Adopt and Implement the NSCoding Protocol

Let’s say that we have a class named Worker that will be archiving content. The first thing to do is adopt the NSCoding protocol in the Worker interface:

#import <Foundation/Foundation.h>

@interface Worker : NSObject<NSCoding>

@property(strong)NSString *name;
@property(strong)NSString *role;

@end

Next, we’ll head to the Worker implementation to implement the two delegate methods associated with NSCoding . These two methods will be used by the archiver to populate object data and to store the object data to a file so we will be letting the class know who to index the property values using key-value coding like scheme.

#import "Worker.h"

@implementation Worker
@synthesize name, role;

-(NSString *)description{
    return [NSString stringWithFormat:@"%@, %@", name, role];
}

- (void) encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:self.name forKey:@"namekey"];
    [encoder encodeObject:self.role forKey:@"rolekey"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    self.name = [decoder decodeObjectForKey:@"namekey"];
    self.role = [decoder decodeObjectForKey:@"rolekey"];
    
    return self;
}

@end

Essentially, we’re associating string keys with property values in these two methods.

Save Objects to Filesystem

Once your class supports archiving you can use the NSKeyedArchiver to save the content to the file system. In iOS, you would need to use the documents directory but Mac apps can save to any directory on your Mac. Here’s an example of how you could do this:

BOOL dataArchived = [NSKeyedArchiver archiveRootObject:workerObject
                                                toFile:@"/Users/Shared/workerObject.dat"];

Of course, this is assuming that you already have a Worker object already set up with content. You can try this from a Mac to see the file that was created easily.

Note to decode the object graph you can use NSKeyedUnarchiver . Does anyone have any thoughts on what this will look like? Please post that code in the comments below!