#UserDefaultsExample
Author: Johnny Slagle
Date: Nov 1st, 2012
This is a very simple example project I created to demonstrate the proper way to store and load custom objects, from NSUserDefaults, using the methods encodeWithCoder and iniWithCoder.
###JSPerson JSPerson is a very basic class that only contains the following two properties:
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *number;
JSPerson implements initWithCoder:
- (id)initWithCoder:(NSCoder *)decoder {
if((self = [super init])) {
self.name = [decoder decodeObjectForKey:JSPersonNameKey];
self.number = [decoder decodeObjectForKey:JSPersonNumberKey];
}
return self;
}
and encodeWithCoder:
- (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:self.name forKey:JSPersonNameKey];
[encoder encodeObject:self.number forKey:JSPersonNumberKey];
}
###JSTableViewController
JSTableViewController is the project's rootViewController is a simple UITableViewController. The data source for it's tableView is an array of JSPerson objects called persons which is lazy instantiation. It is defined as such:
@property (nonatomic, strong) NSMutableArray *persons;
JSTableViewController also stores an array of names that loads ~37 names from the plist Names.plist in the app bundle. A random name is selected when creating a new person. It's defined as such:
@property (nonatomic, strong) NSArray *names;
###Encoding & Decoding
JSTableViewController has the methods that should be looked at to understand how to store and load your objects.
####Storing Persons Array The method to see how to store an array in NSUserDefaults is called savePersons. It looks like this:
- (void) savePersons {
// Save the persons array
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:self.persons]
forKey:JSPersonsArrayKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
It uses NSKeyedArchiver to archive your persons array into NSUserDefaults. The method archivedDataWithRootObject uses JSPerson's encodeWithCoder to create an NSData object.
####Loading Persons Array The loading of the potentially stored persons array is done in it's lazy instantiation method. It looks like this:
- (NSMutableArray *)persons {
if(_persons == nil) {
// Load the NSData back from the NSUserDefaults
NSData *dataRepresentingSavedArray = [[NSUserDefaults standardUserDefaults] objectForKey:JSPersonsArrayKey];
// Is there data there?
if (dataRepresentingSavedArray != nil) {
// Unarchive the NSData into an array. This uses JSPerson's initWithCoder method to do so.
NSMutableArray *oldPersonsArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray];
// Store as persons array if an array is unarchived
if (oldPersonsArray != nil) {
_persons = [[NSMutableArray alloc] initWithArray:oldPersonsArray];
}
} else {
// Create an empty persons array
_persons = [[NSMutableArray alloc] init];
}
}
return _persons;
}
In this method we use the method unarchiveObjectWithData to load the data back from NSUserDefaults. When it does that, NSKeyedArchiver uses JSPerson's initWithCoder method to load the data back into a JSPerson object.