how to save plist to NSUserDefaults

ios, iphone, nsuserdefaults, plist

Solution

You can't write a `.plist` into `NSUserDefaults`, at least not practically. To achieve this you'll have to write specific keys from the `.plist` into `NSUserDefaults` which is basically like saving two copies of all of your data. You can think of `NSUserDefaults` as an invisible `.plist` that you can read and write to, without ever being able to actually see the file. Using `NSUserDefaults`, you will be able to restore saved values even if the app has been killed in multitasking.

However, how you choose between `.plist` and `NSUserDefaults` should be based off of how much data you need to save. Apple recommends only saving small amounts of data to `NSUserDefaults`. If you need to save a lot of information then `.plist` is the way to go. Either that or of course `Core-Data`.

Problem

I am trying to save a `.plist` I have created into my `NSUserDefaults` so that I can save the data that I am putting into it, so if the app is stopped (removed from multitasking bar) I do not loose the values. I have been pointed to this tutorial here In it is has this sample code. ``` -(void)saveToUserDefaults:(NSString*)myString { NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults]; if (standardUserDefaults) { [standardUserDefaults setObject:myString forKey:@"Prefs"]; [standardUserDefaults synchronize]; } } -(NSString*)retrieveFromUserDefaults { NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults]; NSString *val = nil; if (standardUserDefaults) val = [standardUserDefaults objectForKey:@"Prefs"]; return val; } ``` What I would like some help with is how dose the above relate to saving `.plists`? I have a `.plist` controller class which reads the bundle `.plist` creates a new `.plist` in the root document then reads and writes to that... how so I use the above to save it when the app exits or turns off? This is how I am loading and writing to my `.plist`, at the moment using singlettons and it being in its own class. ``` #pragma mark Singleton Methods + (id)sharedManager { @synchronized(self) { if (sharedMyManager == nil) sharedMyManager = [[self alloc] init]; } return sharedMyManager; } - (id)init { if (self = [super init]) { // Data.plist code // get paths from root direcory NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES); // get documents path NSString *documentsPath = [paths objectAtIndex:0]; // get the path to our Data/plist file NSString *plistPath = [documentsPath stringByAppendingPathComponent:@"EngineProperties.plist"]; // check to see if Data.plist exists in documents if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath]) { // if not in documents, get property list from main bundle plistPath = [[NSBundle mainBundle] pathForResource:@"EngineProperties" ofType:@"plist"]; } // read property list into memory as an NSData object NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath]; NSString *errorDesc = nil; NSPropertyListFormat format; // convert static property liost into dictionary object NSDictionary *tempRoot = (NSMutableDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc]; if (!tempRoot) { NSLog(@"Error reading plist: %@, format: %d", errorDesc, format); } // assign values self.signature = [tempRoot objectForKey:@"Signature"]; self.version = [tempRoot objectForKey:@"Version"]; self.request = [tempRoot objectForKey:@"Request"]; self.dataVersion = [tempRoot objectForKey:@"Data Version"]; man = [cacheValue objectForKey:@"Man"]; mod = [cacheValue objectForKey:@"Mod"]; sub = [cacheValue objectForKey:@"SubMod"]; cacheValue = [tempRoot objectForKey:@"Cache Value"]; } - (void) saveData:(NSString *)methodName signature:(NSString *)pSignature Version:(NSNumber *)pVersion request:(NSNumber *)rNumber dataVersion:(NSNumber *)dvReturned cacheValue:(NSNumber *)cValue; { // get paths from root direcory NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES); // get documents path NSString *documentsPath = [paths objectAtIndex:0]; // get the path to our Data/plist file NSString *plistPath = [documentsPath stringByAppendingPathComponent:@"EngineProperties.plist"]; // set the variables to the values in the text fields self.signature = pSignature; self.version = pVersion; self.request = rNumber; self.dataVersion = dvReturned; //do some if statment stuff here to put the cache in the right place or what have you. if (methodName == @"manufacturers") { self.man = cValue; } else if (methodName == @"models") { self.mod = cValue; } else if (methodName == @"subMod") { self.sub = cValue; } self.cacheValue = [NSDictionary dictionaryWithObjectsAndKeys: man, @"Manufacturers", mod, @"Models", sub, @"SubModels", nil]; NSDictionary *plistDict = [NSDictionary dictionaryWithObjectsAndKeys: signature, @"Signature", version, @"Version", request, @"Request", dataVersion, @"Data Version", cacheValue, @"Cache Value", nil]; NSString *error = nil; // create NSData from dictionary NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:plistDict format:NSPropertyListXMLFormat_v1_0 errorDescription:&error]; // check is plistData exists if(plistData) { // write plistData to our Data.plist file [plistData writeToFile:plistPath atomically:YES]; NSString *myString = [[NSString alloc] initWithData:plistData encoding:NSUTF8StringEncoding]; // NSLog(@"%@", myString); } else { NSLog(@"Error in saveData: %@", error); // [error release]; } } @end ```

Original source