NSCoding
will do exactly what you want. I recommend you read up on it in the Apple docs, but I thought it was pretty straightforward to use. Your class (and any child classes) will need to implement the NSCoding
protocol and you'll need to add -encodeWithCoder:
and -initWithCoder:
methods to your objects. Most of the common framework classes implement NSCoding
already.
The code for your class will look something like this:
-(void) encodeWithCoder: (NSCoder*) coder {
[coder encodeInteger: versionValue forKey: versionKey];
[coder encodeObject: myStuff forKey: myStuffKey];
}
-(id) initWithCoder: (NSCoder*) coder {
self = [super init];
if ( ! self) return nil;
myStuff = [[coder decodeObjectForKey: myStuffKey] retain];
return self;
}
It's recommended you add a version number when encoding to give you flexibility to manage changes to your archive format in future versions.
In my class, I added a convenience method to archive my object:
-(void) archiveToFile: (NSString*) path {
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData: data];
[archiver encodeObject: self forKey: myArchiveKey];
[archiver finishEncoding];
[archiver release];
[data writeToFile: path atomically: YES];
[data release];
}
and another one to unarchive or create a new object:
+(MyArchive*) newFromFile: (NSString*) path
orWithMyStuff: (MyStuff*) myStuff
{
NSData *data = [[NSData alloc] initWithContentsOfFile: path];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData: data];
MyArchive *myArchive = [unarchiver decodeObjectForKey: myArchiveKey];
[unarchiver finishDecoding];
if (myArchive) {
[myArchive retain];
} else {
myArchive = [[MyArchive alloc] initWithStuff: myStuff;
}
[unarchiver release];
[data release];
return myArchive;
}
Since your top level object is an NSArray
, you'll need to modify the last two methods for your case, but most of the boilerplate code will be the same.