Of course, there is nothing wrong with saving NSUserDefaults, but if you want to save your properties to disk, I collected some code for you to save to a .plist file, and then later extract it. You can also find it in gist .
Preservation
// We're going to save the data to SavedState.plist in our app documents directory NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString *plistPath = [rootPath stringByAppendingPathComponent:@"SavedState.plist"]; // Create a dictionary to store all your data NSMutableDictionary *dataToSave = [NSMutableDictionary dictionary]; // Store any NSData, NSString, NSArray, NSDictionary, NSDate, and NSNumber directly. See "NSPropertyListSerialization Class Reference" for more information. NSString *myString = @"Hello!" [dataToSave setObject:myString forKey:@"MyString"]; // Wrap primitives in NSValue or NSNumber objects. Here are some examples: BOOL someBool = YES; NSNumber *boolValue = [NSNumber numberWithBool:someBool]; [dataToSave setObject:boolValue forKey:@"SomeBoolValue"]; int someInteger = 99; NSInteger *integerValue = [NSNumber numberWithInteger:someInteger]; [dataToSave setObject:integerValue forKey:@"SomeIntegerValue"]; // Any objects that conform to NSCoding can be archived to an NSData instance. In this example, MyClass conforms to NSCoding. MyClass *someObject = [[MyClass alloc] init]; NSData *archivedStateOfSomeObject = [NSKeyedArchiver archivedDataWithRootObject:someObject]; [dataToSave setObject:archivedStateOfSomeObject forKey:@"SomeObject"]; // Create a serialized NSData instance, which can be written to a plist, from the data we've been storing in our NSMutableDictionary NSString *errorDescription; NSData *serializedData = [NSPropertyListSerialization dataFromPropertyList:dataToSave format:NSPropertyListXMLFormat_v1_0 errorDescription:&errorDescription]; if(serializedData) { // Write file NSError *error; BOOL didWrite = [serializedData writeToFile:plistPath options:NSDataWritingFileProtectionComplete error:&error]; NSLog(@"Error while writing: %@", [error description]); if (didWrite) NSLog(@"File did write"); else NSLog(@"File write failed"); } else { NSLog(@"Error in creating state data dictionary: %@", errorDescription); }
Loading
// Fetch NSDictionary containing possible saved state NSString *errorDesc = nil; NSPropertyListFormat format; NSString *plistPath; NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; plistPath = [rootPath stringByAppendingPathComponent:@"SavedState.plist"]; NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath]; NSDictionary *unarchivedData = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc]; // If NSDictionary exists, look to see if it holds a saved game state if (!unarchivedData) { NSLog(@"Error reading plist: %@, format: %d", errorDesc, format); } else { // Load property list objects directly NSString *myString = [unarchivedData objectForKey:@"MyString"]; // Load primitives NSNumber *boolValue = [unarchivedData objectForKey:@"SomeBoolValue"]; BOOL someBool = [boolValue boolValue]; NSNumber *integerValue = [unarchivedData objectForKey:@"SomeIntegerValue"]; BOOL someBool = [integerValue integerValue]; // Load your custom objects that conform to NSCoding NSData *someObjectData = [unarchivedData objectForKey:@"SomeObject"]; MyClass *someObject = [NSKeyedUnarchiver unarchiveObjectWithData:someObjectData]; }
For further reading, see the Archive Programming and Serialization Guide .
source share