1
votes

Previously, I have an array in which I use NSKeyedArchiver to archieve.

[NSKeyedArchiver archiveRootObject:array toFile:docPath];

Called on applicationWillTerminate and applicationDidEnterBackground.

Upon starting up, in didFinishLaunchingWithOPtions, the array is unarchieved:

NSMutableArray *array = [NSKeyedUnarchiver unarchiveObjectWithFile:docPath];

Everything was good. Since then, I added a Singleton class for Settings variables. I would like to archive the Singleton as well. How would I do that?

The part that confuses me is if I call the same message:

[NSKeyedArchiver archiveRootObject:singleton toFile:docPath];

How can the app know which object I want to unarchive when I call:

[NSKeyedUnarchiver unarchiveObjectWithFile:docPath];

Is it the array or the singleton?

The archiveRootObject accepts an (id) which to me means whatever I want. I can create a data class which includes the array and the singleton. Is that how I am suppose to do this? Is there a better way? Any suggestions are welcomed.

Thanks!

2

2 Answers

3
votes

If you want to encode more than one object at the root level, you'll need to create the archiver using +alloc and -initForWritingWithMutableData: yourself, send it -encodeObject:forKey: messages for each of the objects you want to add to the archive, and finally -finishEncoding. You can then write the data to a file yourself.

It'll look something like this (warning: untested code ahead):

NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];

[archiver encodeObject:someObject forKey:@"people"];
[archiver encodeObject:anotherObject forKey:@"places"];
[archiver encodeObject:thirdObject forKey:@"things"];
[archiver finishEncoding];

[data writeToURL:someUrl atomically:YES];
[archiver release];

To retrieve the objects, you'll do essentially the opposite: read a file into an NSData object; create an NSKeyedUnarchiver with +alloc and -initForReadingWithData:; retrieve the objects you care about using -decodeObjectForKey:; and finally call -finishDecoding. You can almost read the sample above from bottom to top with a few name changes.

3
votes

To be archivable, your singleton class must conform to the NSCoding protocol. You will have to implement its initWithCoder: and encodeWithCoder: methods.

Again if you do archiveRootObject:toFile: on two objects with the same file path then you will overwrite one of them. To encode two objects, you will have to do something like this,

NSData * data = [NSMutableData data];
NSKeyedArchiver * archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; 
[archiver encodeObject:array forKey:@"Array"];
[archiver encodeObject:singleton forKey:@"Singleton"];
[archiver finishEncoding];
BOOL result = [data writeToFile:filePath atomically:YES];
[archiver release];

You can read more on archiving in this guide.