How to read data structure from .plist file into NSArray
Asked Answered
A

8

49

I was creating a data structure manually using the following:

NSDictionary* league1 = [[NSDictionary alloc] initWithObjectsAndKeys: @"Barclays Premier League", @"name",
                 @"Premier League", @"shortname",
                 @"101", @"id", nil];
NSDictionary* league2 = [[NSDictionary alloc] initWithObjectsAndKeys: @"Coca-Cola Championship", @"name",
                 @"Championship", @"shortname",
                 @"102", @"id", nil];
NSDictionary* league3 = [[NSDictionary alloc] initWithObjectsAndKeys: @"Scottish Premier League", @"name",
                 @"SPL", @"shortname",
                 @"201", @"id", nil];
NSDictionary* league4 = [[NSDictionary alloc] initWithObjectsAndKeys: @"Champions League", @"name",
                 @"UCL", @"shortname",
                 @"501", @"id", nil];

contentArray = [[NSArray alloc] initWithObjects:

                [[NSDictionary alloc] initWithObjectsAndKeys: @"English", @"category", [[NSArray alloc] initWithObjects: league1, league2, nil], @"leagues", nil],
                [[NSDictionary alloc] initWithObjectsAndKeys: @"Scottish", @"category", [[NSArray alloc] initWithObjects: league3, nil], @"leagues", nil],
                [[NSDictionary alloc] initWithObjectsAndKeys: @"Tournaments", @"category", [[NSArray alloc] initWithObjects: league4, nil], @"leagues", nil],
                nil];

[league1 release];
[league2 release];
[league3 release];
[league4 release];

However, I thought this would be better if it was read from a file. So I created the file leagues.plist which has the following structure:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <array>
        <dict>
            <key>category</key>
            <string>English</string>
            <key>leagues</key>
            <array>
                <dict>
                    <key>name</key>
                    <string>Barclays Premier League</string>
                    <key>shortname</key>
                    <string>Premier League</string>
                    <key>id</key>
                    <string>101</string>
                </dict>
                <dict>
                    <key>name</key>
                    <string>Coca-Cola Championship</string>
                    <key>shortname</key>
                    <string>Championship</string>
                    <key>id</key>
                    <string>102</string>
                </dict>
            </array>
        </dict>
        <dict>
            <key>category</key>
            <string>Scottish</string>
            <key>leagues</key>
            <array>
                <dict>
                    <key>name</key>
                    <string>Scottish Premier League</string>
                    <key>shortname</key>
                    <string>SPL</string>
                    <key>id</key>
                    <string>201</string>
                </dict>
            </array>
        </dict>
        <dict>
            <key>category</key>
            <string>Tournaments</string>
            <key>leagues</key>
            <array>
                <dict>
                    <key>name</key>
                    <string>Champions League</string>
                    <key>shortname</key>
                    <string>UCL</string>
                    <key>id</key>
                    <string>501</string>
                </dict>
            </array>
        </dict>
    </array>
</plist>

How do I read this file in. I have tried various methods but nothing has worked. I don't even know if I am looking in the right place for the file. For reference I am trying the following methods:

NSString* errorDesc = nil;
NSPropertyListFormat format;
NSString* plistPath = [[NSBundle mainBundle] pathForResource:@"league" ofType:@"plist"];
NSData* plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
contentArray = (NSArray*)[NSPropertyListSerialization
                                     propertyListFromData:plistXML
                                     mutabilityOption:NSPropertyListMutableContainersAndLeaves
                                     format:&format
                                     errorDescription:&errorDesc];

if (!contentArray) {
    NSLog(errorDesc);
    [errorDesc release];
}

or

NSString* plistPath = [[NSBundle mainBundle] pathForResource:@"league" ofType:@"plist"];
contentArray = [NSArray arrayWithContentsOfFile:plistPath];

or

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];

NSString *fooPath = [documentsPath stringByAppendingPathComponent:@"leagues.plist"];
NSLog(fooPath);
contentArray = [NSArray arrayWithContentsOfFile:fooPath];
NSLog(@"%@",contentArray);

This is finally driving me completely insane. Help please!

Thank you kindly

Amorete answered 14/4, 2009 at 21:52 Comment(0)
A
121
NSString* plistPath = [[NSBundle mainBundle] pathForResource:@"league" ofType:@"plist"];
contentDict = [NSDictionary dictionaryWithContentsOfFile:plistPath];

That answer is correct - are you sure that your file is in the app? Did you add it to your project, and check to see if it gets copied into your app bundle? If not, it might be the file was not added to the target you are building, an easy mistake to make especially if you have multiple targets.

Alsoran answered 15/4, 2009 at 5:56 Comment(4)
Just learning here :). I don't know if it is in the main bundle. Thanks I will check that next.Amorete
It is: [NSDictionary dictionaryWithContentsOfFile:plistPath];Peafowl
contentArray =>> should be contentDictStaggers
Thanks @TàTruhoada, fixed.Alsoran
Y
4

Use this code if the plist is in the resources folder of the project.

  NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"league"    ofType:@"plist"];
 contentArray = [NSArray arrayWithContentsOfFile:sourcePath];

If the plist is inside the document directory of the app use this:

    NSArray *paths = 
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;

NSString *plistName = @"league";
NSString *finalPath = [basePath stringByAppendingPathComponent: 
                       [NSString stringWithFormat: @"%@.plist", plistName]];



contentArray = [NSArray arrayWithContentsOfFile:finalPath];
Yvonneyvonner answered 7/6, 2011 at 12:45 Comment(0)
H
4

I had this issue but it wasn't working because I was putting the results from the pList into an array where it should have been a dictionary, i.e

NSString* plistPath = [[NSBundle mainBundle] pathForResource:@"VehicleDetailItems" ofType:@"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
Harpoon answered 17/5, 2012 at 13:56 Comment(0)
S
2

Kendall is correct.

In my experience, you need to add your file to the "Resources" folder in xcode.

Straphanger answered 15/4, 2009 at 8:16 Comment(2)
What about a folder inside the Resources folder? Can it also be added there?Quesenberry
@Quesenberry that's okay, just make sure it is relative to group.Cooky
A
2

For completeness, Kendall and bentford are completely correct. However, in my sample, contentArray was a property and by the end of the method it was going out of scope because arrayWithContentsOfFile creates an auto-released object.

To make this work correctly I needed to do 3 things:

  1. put the file in the resources folder

  2. name the file correctly (was leagues.plist instead of league.plist)

  3. read the file using [[NSArray alloc] initWithContentsOfFile:plistPath)];

the third part creates an allocated NSArray that does not release when you exit the scope of this function... of course, this needed to be released in the dealloc function.

Amorete answered 17/4, 2009 at 8:50 Comment(1)
for the autorelease thing.. you can just "retain" where appropriate.Yeanling
S
0

Just to add. I had the same problem and the suggested solution helped me solve the problem, however I am not sure if I actually used the exact solution. In my case the problem was that the .plist file was added to a different target (had added a new target a moment before). Therefore the solution was .plist > Get Info > Targets, and make sure it is added to the correct target so it gets copied to device when installing. Darn had I figure that out soon enough I would have saved a lot of time. Hope this is helpful too. Regards!

Schnauzer answered 28/8, 2009 at 6:8 Comment(0)
R
0

If the file is not added in the resources folder and only placed in your documents directory. You can do this

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"file.plist"];
NSMutableArray *arrContentsplist = [[NSMutableArray alloc] initWithContentsOfFile:path];
Roanne answered 10/1, 2013 at 12:53 Comment(0)
F
0

This Code is working

NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"plist-name" ofType:@"plist"];
NSDictionary *Dictionary= [[NSDictionary alloc]initWithContentsOfFile:plistPath];
NSLog(@" current version CFBundleVersion = %@",[Dictionary valueForKey:@"CFBundleVersion"]);
Fluent answered 14/2, 2013 at 10:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.