Take the 2-minute tour ×

I'm having several issues based around reading and writing an NSArray to and from a plist.

I have created a plist file in the 'Supporting Files' folder which I want to use to initialise the app data with upon the first load.

Here is what my plist looks like:

enter image description here

I then use this code to try load the plist into the app:

    NSError *error;
    NSString *documentsDirectory = [paths objectAtIndex:0];
    filePath = [documentsDirectory stringByAppendingPathComponent:kDataFile];

    NSFileManager *fileManager = [NSFileManager defaultManager];
    if (![fileManager fileExistsAtPath:filePath])
        NSString *bundle = [[NSBundle mainBundle] pathForResource:@"Data" ofType:@"plist"];
        [fileManager copyItemAtPath:bundle toPath:filePath error:&error];

I then try to load the data from the plist file like so, however nothing seems to be displayed.

NSMutableDictionary *savedData = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
NSMutableArray *myNSArray = [[savedData objectForKey:@"KEY_Level_1"] mutableCopy];
savedData = nil;

Sorry if this is a simple task, however I've been looking at lots of tutorials and trying to work out how to do this with no luck. I'm getting really frustrated now - I would have thought it should be a simple thing to do.

NOTE: My NSArray will contain a whole bunch of NSDictionaries.

share|improve this question
You need to put log statements or step through with the debugger at each stage and see where it is failing. Check all your paths are set to what you expect, see if the file is copied, and so forth. Nothing looks obviously wrong with your code. Is the file the same case as your code? Is the plist included in the target? –  jrturton Dec 20 '11 at 19:05
add comment

1 Answer

up vote 0 down vote accepted
  1. You need to check the return value of copyItemAtPath:toPath:error: and at least log the error if the method returns false:

    if (![fileManager copyItemAtPath:bundle toPath:filePath error:&error]) {
        NSLog(@"error: copyItemAtPath:%@ toPath:%@ error:%@", bundle, filePath, error);
  2. -[NSDictionary initWithContentsOfFile:] has no way to report errors, so if it's failing, you cannot easily figure out why. Try reading the file into an NSData and using -[NSPropertyListSerialization propertyListWithData:options:format:error:] to parse it:

    NSData *data = [NSData dataWithContentsOfFile:filePath options:0 error:&error];
    if (!data) {
        NSLog(@"error: could not read %@: %@", filePath, error);
    NSMutableDictionary *savedData = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListMutableContainers format:NULL error:&error];
    if (!savedData) {
        NSLog(@"error: could not parse %@: %@", filePath, error);
    NSMutableArray *myNSArray = [savedData objectForKey:@"KEY_Level_1"];
    savedData = nil;
    if (!myNSArray) {
        NSLog(@"error: %@: object for KEY_Level_1 missing", filePath);

If you do this, you'll be able to more easily see why your data is not being loaded.


On further inspection, it looks like the top-level dictionary in your plist contains the key "Root". The value for "Root" is a dictionary containing the key "KEY_Level_1". So you need to do this:

NSMutableArray *myNSArray = [[savedData objectForKey:@"Root"] objectForKey:@"KEY_Level_1"];
share|improve this answer
...or [savedData valueForKeyPath:@"Root.KEY_Level_1"]. –  jlehr Dec 20 '11 at 19:41
add comment

Your Answer


