When a class conforms to the NSCoding protocol it can be archived and later loaded into the application.
Archiving is very simple to use. To make a class suitable for archiving you simply need to use the NSCoding delegate and implement the encodeWithEncoder and initWithEncoder funcitons. The class is then ready to be stored and retrieved using the NSKeyed methods.
If you use a Singleton class in your project (a global class) which has all the settings you need to save then you can make any special classes it uses NSCoding ready and use the later example code within the singleton class to read and write the objects that need to be stored to non volatile memory.
Making A Class You've Created Conform To NSCoding So You Can Archive It
In MyClass.h
@interface MyClass : NSObject
<NSCoding> //This is needed for archiving
{
In MyClass.m
//*************************************************
//*************************************************
//********** ARCHIVE - ENCODE WITH CODER **********
//*************************************************
//*************************************************
//This function makes us conform to NSCoding and encodes our class members for archive file writing
- (void)encodeWithCoder:(NSCoder *)encoder
{
//Archive each instance varaible using its name
[encoder encodeObject:SomeStringName forKey:@"aSomeStringName"];
[encoder encodeInt:SomeIntName forKey:@"aSomeIntName"];
[encoder encodeBool:SomeBoolName forKey:@"aSomeBoolName"];
}
//***********************************************
//***********************************************
//********** ARCHIVE - INIT WITH CODER **********
//***********************************************
//***********************************************
//This function makes us conform to NSCoding and decodes our class members from archive file reading
- (id)initWithCoder:(NSCoder *)decoder
{
[super init];
//Decode each instance variable that is archived and pass to our property set methods
[self setSomeStringName:[decoder decodeObjectForKey:@"aSomeStringName"]]; //--Notice the 'set' at the start of the variable/object name
[self setSomeIntName:[decoder decodeIntForKey:@"aSomeIntName"]];
[self setSomeBoolName:[decoder decodeBoolForKey:@"aSomeBoolName"]];
return self;
}
To Read & Write A Global Singleton Class Using Archiving
Add to the classes .h file
- (void)saveSettings;
In the classes init method
//**************************
//**************************
//********** INIT **********
//**************************
//**************************
-(id)init
{
if (self = [super init])
{
//----- READ CLASS FROM FILE -----
NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [documentDirectories objectAtIndex:0];
NSString *myFilePath = [documentDirectory stringByAppendingPathComponent:@"MyFileName.data"];
NSData *settingsData = [[NSMutableData alloc] initWithContentsOfFile:myFilePath];
if (settingsData)
{
//----- EXISTING DATA EXISTS -----
NSKeyedUnarchiver *decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:settingsData];
self.Reminders = [decoder decodeObjectForKey:@"aReminders"];
//Decode each instance variable/object that is archived
self.SomeArrayName = [decoder decodeObjectForKey:@"aSomeArrayName"];
self.SomeStringName = [decoder decodeObjectForKey:@"aSomeStringName"];
self.SomeIntName = [decoder decodeIntForKey:@"aSomeIntName"];
self.SomeBoolName = [decoder decodeBoolForKey:@"aSomeBoolName"];
[decoder finishDecoding];
[decoder release];
[settingsData release];
}
else
{
//----- NO DATA EXISTS -----
SomeArrayName = [[SomeArrayName alloc] init];
}
}
return self;
}
Create A Save Settings Method
//***********************************
//***********************************
//********** SAVE SETTINGS **********
//***********************************
//***********************************
-(void)saveSettings
{
NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [documentDirectories objectAtIndex:0];
NSString *myFilePath = [documentDirectory stringByAppendingPathComponent:@"MyFileName.data"];
NSMutableData *settingsData = [NSMutableData data];
NSKeyedArchiver *encoder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:settingsData];
//Archive each instance variable/object using its name
[encoder encodeObject:self.SomeArrayName forKey:@"aSomeArrayName"];
[encoder encodeObject:self.SomeStringName forKey:@"aSomeStringName"];
[encoder encodeInt:self.SomeIntName forKey:@"aSomeIntName"];
[encoder encodeBool:self.SomeBoolName forKey:@"aSomeBoolName"];
[encoder finishEncoding];
[settingsData writeToFile:myFilePath atomically:YES];
[encoder release];
}
Call It In applicationWillTerminate, applicationDidEnterBackground and anywhere else you want to ensure settings get saved
//Save our global class
[[AppMain sharedAppMain] saveSettings];
To Read & Write A Sub Class Using Archiving
In #ApplicationDelegate.m applicationDidFinishLaunchingWithOptions
//----- READ CLASS FROM FILE -----
NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [documentDirectories objectAtIndex:0];
NSString *myFilePath = [documentDirectory stringByAppendingPathComponent:@"MyFileName.data"];
NSMutableArray *myClassArray = [NSKeyedUnarchiver unarchiveObjectWithFile:myFilePath]; //Unarchive it to our array
if (!myClassArray)
myClassArray = [NSMutableArray array]; //There was no file so create empty array
In #ApplicationDelegate.m applicationWillTerminate
//********** APPLICATION WILL TERMINATE **********
//(Called when the application is about to terminate. See also applicationDidEnterBackground)
- (void)applicationWillTerminate:(UIApplication *)application
{
//----- STORE CLASS FILE -----
NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [documentDirectories objectAtIndex:0];
NSString *myFilePath = [documentDirectory stringByAppendingPathComponent:@"MyFileName.data"];
NSMutableArray *arrayToStore = myClassArray;
[NSKeyedArchiver archiveRootObject:arrayToStore toFile:myFilePath];
}