Jon
Jon

Reputation: 4732

Need help creating .plist in app

My app ships with a .plist that looks like this:

enter image description here

I want the user to be able to add a custom exerciseName.

So I need to create a new .plist in the user's document folder that mimics this format. Can anyone help me with this?

I need something like this (pseudo code)

if (userData == nil)
{
     then create the .plist file;
     setup the .plist to mimic the format of the img above.
} 
now save exerciseName appropriately.

Update:

if (exerciseArray == nil)
{
    NSString *path = [[NSBundle mainBundle]pathForResource:@"data" ofType:@"plist"];
    NSMutableArray *rootLevel = [[NSMutableArray alloc]initWithContentsOfFile:path];
    self.exerciseArray = rootLevel;
    [rootLevel release];
}

Upvotes: 2

Views: 354

Answers (2)

Alex Nichol
Alex Nichol

Reputation: 7510

What you will want to do is load the Plist into an NSDictionary, and encode that NSDictionary back to a Plist file in your applications document folder. In your applicationDidFinishLoading: method, I would do something like this:

NSString * documentFile = [NSHomeDirectory() stringByAppendingFormat:@"/Documents/myPlist.plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath:documentFile]) {
    // create a copy of our resource
    NSString * resPath = [[NSBundle mainBundle] pathForResource:@"myPlist" ofType:@"plist"];
    // NOTE: replace @"myPlist" with the name of the file in your Resources folder.
    NSDictionary * dictionary = [[NSDictionary alloc] initWithContentsOfFile:resPath];
    [dictionary writeToFile:documentFile atomically:YES];
    [dictionary release];
}

Then, when you want to add an item, you want to use an NSMutableDictionary to modify and save the existing plist in the app's documents directory:

- (void)addExercise {
    NSMutableDictionary * changeMe = [[NSMutableDictionary alloc] initWithContentsOfFile:documentFile];
    ... make changes ...
    [changeMe writeToFile:documentFile atomically:YES];
    [changeMe release];
}

To make changes, you will need to find the sub-dictionary containing the array of exercises. Then use the setObject:forKey: method on the NSMutableDictionary to set a new array containing a new list of exercises. This might look something like this:

NSMutableArray * list = [NSMutableArray arrayWithArray:[changeMe objectForKey:@"list"]];
NSArray * exercises = [[list objectAtIndex:10] objectForKey:@"exercises"];
NSDictionary * newExercise = [NSDictionary dictionaryWithObject:@"Type a LOT" forKey:@"exerciseName"];
exercises = [exercises arrayByAddingObject:newExercise];
NSMutableDictionary * dict = [NSMutableDictionary dictionaryWithDictionary:[list objectAtIndex:10]];
[dict setObject:exercises forKey:@"exercises"];
[list replaceObjectAtIndex:10 withObject:dict];
[changeMe setObject:list forKey:@"list"];

Once you make your change, it is important to remember to write changeMe to the plist file in the documents directory.

Upvotes: 1

ughoavgfhw
ughoavgfhw

Reputation: 39905

The easiest way to read and write property lists is to use the NSArray or NSDictionary classes. Your screenshot appears to be an array at the top level, so I will use that assumption for my examples.

First you need paths to the user file and original file.

NSString *pathToUserFile; // Get a path to the file in the documents directory
NSString *pathToDefaultFile; // Get a path to the original file in the application bundle

You then attempt to load the

NSMutableArray *userData;
NSArray *temporary = [NSArray arrayWithContentsOfFile:pathToUserFile];
if(!temporary) temporary = [NSArray arrayWithContentsOfFile:pathToDefaultFile];

Since it appears that you are using multiple layers containers, I am assuming that you will need the innermost arrays and dictionaries to be mutable. The normal initialization of NSMutableArray will not do this, so you need to use CFPropertyListCreateDeepCopy with the options set to have mutable containers.

userData = (NSMutableArray *)CFPropertyListCreateDeepCopy(NULL,(CFArrayRef)temporary,kCFPropertyListMutableContainers);

You now have a mutable object representing your data. You can add objects or modify existing objects the same way you handle any array, but you can only add strings, numbers, data objects, dictionaries, arrays, and dates, since those are the only types valid in property lists.

[userData addObject:newDataObject];

Finally, you write the data out to the file in the documents directory. The writeToFile:atomically: method will attempt to write out a property list, and return YES if successful. It will fail and return NO if the file could not be written, or if the contents are not all valid property list objects.

if(![userData writeToFile:pathToUserFile atomically:YES]) {
    NSLog(@"Error writing to file");
}

Upvotes: 1

Related Questions