Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

lxLionHartxl

macrumors newbie
Original poster
Jul 20, 2011
6
0
Hi,

I have a problem reading from my plist file. I have tried multiple methods and none are working. I am stuck on this for a long time. I have already seek countless helps and looked up for solutions. I don't know why is this taking too long for me to solve. So I need your help.

Code:
NSError *error;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //1
    NSString *documentsDirectory = [paths objectAtIndex:0]; //2
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"EventAddress.plist"]; //3
    NSLog(@"%@", path);
    NSFileManager *fileManager = [NSFileManager defaultManager];
    
    if (![fileManager fileExistsAtPath: path]) //4
    {
        NSString *bundle = [[NSBundle mainBundle] pathForResource:@"EventAddress" ofType:@"plist"]; // 5
        
        [fileManager copyItemAtPath:bundle toPath: path error:&error]; //6
    }
    
    NSString *pathss = [[NSBundle mainBundle] bundlePath];
    NSLog(@"%@", pathss);
    NSArray* plist = [NSArray arrayWithContentsOfFile:path];
    NSLog(@"%@", plist);

The last few lines are used because each time I want to assign the NSArray to the path location, I get 0x0 (nil). Below is the image of my plist.

plist.png
 
1. You have 3 NSLog()'s in your code. Post their output, so we can see what you see when the code runs.

2. Add an NSLog() before copyItemAtPath: that shows the actual path of the 'bundle' variable. Rerun the program and post the output.

3. Add a check for the existence of a file at the path given by the 'bundle' variable. That is, confirm that the file you're trying to copy from exists. Post the output.

4. You don't check the BOOL returned from copyItemAtPath:, so you have no way to tell whether it worked or it failed.


The basic principle of all debugging is to confirm what you expect. If you don't confirm something, and blindly assume it works as expected, you can be wrong.

If confirmation means checking the result after every step of a procedure, then that's what you have to do. You will find at a certain point that learning to use the debugger, and using it to step through procedures, is more useful than throwing in dozens of NSLog()'s.
 
1. You have 3 NSLog()'s in your code. Post their output, so we can see what you see when the code runs.

Code:
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"EventAddress.plist"]; //3
    NSLog(@"%@", path);
/Users/melvinlai/Library/Application Support/iPhone Simulator/4.3.2/Applications/98E03140-5556-4EE9-B7E3-043247E96D10/Documents/EventAddress.plist

Code:
NSString *pathss = [[NSBundle mainBundle] bundlePath];
    NSLog(@"%@", pathss);

/Users/melvinlai/Library/Application Support/iPhone Simulator/4.3.2/Applications/98E03140-5556-4EE9-B7E3-043247E96D10/EventsLocator.app

Code:
NSArray* plist = [NSArray arrayWithContentsOfFile:path];
    NSLog(@"%@", plist);

2011-08-25 11:18:45.211 EventsLocator[7240:207] (null)
This is the part I am most concern.

2. Add an NSLog() before copyItemAtPath: that shows the actual path of the 'bundle' variable. Rerun the program and post the output.

Code:
NSString *bundle = [[NSBundle mainBundle] pathForResource:@"EventAddress" ofType:@"plist"];

Users/melvinlai/Library/Application Support/iPhone Simulator/4.3.2/Applications/98E03140-5556-4EE9-B7E3-043247E96D10/EventsLocator.app/EventAddress.plist

3. Add a check for the existence of a file at the path given by the 'bundle' variable. That is, confirm that the file you're trying to copy from exists. Post the output.

By looking at the log files, cant I confirm that it exists?

4. You don't check the BOOL returned from copyItemAtPath:, so you have no way to tell whether it worked or it failed.

Since there is a ! in the if statement, that sentence is returning a FALSE. I made it TRUE to answer your 2nd request.
 
By looking at the log files, cant I confirm that it exists?

Not with your posted code. Your current code doesn't check whether the original file exists. It simply makes a path and then tries to copy from that path. If the bundle isn't building correctly, then what you expect (the file located at EventsLocator.app/EventAddress.plist) isn't really there.

Confirming every step means exactly that: confirming every step, even the ones you firmly believe can't possibly be going wrong. Confirmation requires evidence. Without evidence, you haven't confirmed anything.

You also haven't shown the code that tests the result returned from copyItemAtPath:. Describing the code is not the same as showing the code.

Post your complete revised code, with the added NSLog()'s and any other changes. Also post a complete copy-and-paste of the NSLog() output, in a single post. We should be able to read the complete code, and the complete output, and the exact sequence should be clear. Posting only pieces makes it harder to understand what's happening overall.
 
Last edited:
.

Code:
-(void)readFile{
    NSError *error;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //1
    NSString *documentsDirectory = [paths objectAtIndex:0]; //2
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"EventAddress.plist"]; //3
    NSLog(@"%@", path);
    NSFileManager *fileManager = [NSFileManager defaultManager];
    
    if ([fileManager fileExistsAtPath: path]) //4
    {
        NSString *bundle = [[NSBundle mainBundle] pathForResource:@"EventAddress" ofType:@"plist"]; // 5
        NSLog(@"%@", bundle);
        [fileManager copyItemAtPath:bundle toPath: path error:&error]; //6
        NSLog(@"%@", fileManager);
    }
    
    NSString *pathss = [[NSBundle mainBundle] bundlePath];
    NSLog(@"%@", pathss);
    NSMutableArray *plist = [[[[NSDictionary dictionaryWithContentsOfFile:path] objectForKey:@"New Item"] mutableCopy] autorelease];
    NSLog(@"%@", plist);
}

NSLog below.

011-08-25 13:22:41.345 EventsLocator[8389:207] /Users/melvinlai/Library/Application Support/iPhone Simulator/4.3.2/Applications/98E03140-5556-4EE9-B7E3-043247E96D10/Documents/EventAddress.plist

2011-08-25 13:22:46.721 EventsLocator[8389:207] /Users/melvinlai/Library/Application Support/iPhone Simulator/4.3.2/Applications/98E03140-5556-4EE9-B7E3-043247E96D10/EventsLocator.app/EventAddress.plist

2011-08-25 13:22:48.374 EventsLocator[8389:207] <NSFileManager: 0x5807dc0>

2011-08-25 13:22:50.633 EventsLocator[8389:207] /Users/melvinlai/Library/Application Support/iPhone Simulator/4.3.2/Applications/98E03140-5556-4EE9-B7E3-043247E96D10/EventsLocator.app

2011-08-25 13:22:52.535 EventsLocator[8389:207] (null)


Is this alright?
 
solution

Hi,

do reply about this still. But I managed to find a code that got it working for me already. The codes are below. Thanks chown33 for your effort :)

Code:
NSString *path = [[NSBundle mainBundle] pathForResource:@"EventAddress" ofType:@"plist"]; 
    NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
    
    
    NSArray* allmyKeys = [myDictionary  allValues];
    NSLog(@"%@", allmyKeys);
    NSLog(@"%@", [[allmyKeys objectAtIndex:0] objectAtIndex:0]);

The last 2 NSLog is used to see if my plist does return an array of values and to find out the value of only 1 of them. And thanks a lot about the debugger, after looking at it for almost 3 days straight, I also realized my problem. The damn array isn't the normal one dimension, its TWO DIMENSION. Thats why I used objectAtIndex twice. :)
 
Code:
-(void)readFile{
    NSError *error;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //1
    NSString *documentsDirectory = [paths objectAtIndex:0]; //2
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"EventAddress.plist"]; //3
    NSLog(@"%@", path);
    NSFileManager *fileManager = [NSFileManager defaultManager];
    
    if ([fileManager fileExistsAtPath: path]) //4
    {
        NSString *bundle = [[NSBundle mainBundle] pathForResource:@"EventAddress" ofType:@"plist"]; // 5
        NSLog(@"%@", bundle);
        [fileManager copyItemAtPath:bundle toPath: path error:&error]; //6
        NSLog(@"%@", fileManager);
    }
    
    NSString *pathss = [[NSBundle mainBundle] bundlePath];
    NSLog(@"%@", pathss);
    NSMutableArray *plist = [[[[NSDictionary dictionaryWithContentsOfFile:path] objectForKey:@"New Item"] mutableCopy] autorelease];
    NSLog(@"%@", plist);
}
...
Is this alright?
It's not what I suggested:
3. Add a check for the existence of a file at the path given by the 'bundle' variable. That is, confirm that the file you're trying to copy from exists. Post the output.

4. You don't check the BOOL returned from copyItemAtPath:, so you have no way to tell whether it worked or it failed.
You aren't doing either of those things.

To do #3, you'd add code something like this (untested, typed in directly):
Code:
BOOL exists = [fileManager fileExistsAtPath: bundle];
NSLog(@"bundle exists: %d", (int)exists );
This should go before the copyItemAtPath:bundle.

To do #4, you'd add code something like this (also untested):
Code:
BOOL copied = [fileManager copyItemAtPath:bundle toPath: path error:&error]; //6
NSLog(@"copied: %d", (int) copied );
if ( ! copied )
{  ... do something to handle the error ... }

If the output confirms that the file exists, and is correctly copied, then you have evidence it was actually copied. If the output shows otherwise, then you have evidence it wasn't.

The NSLog of fileManager is misplaced, if you expect it to be confirmation of a non-nil NSFileManager. It should be placed before the first use of fileManager. Then you can say it confirms the object's existence before it's used. Where it's placed now, it's too late to confirm anything.

Confirmation is a step-by-step trail of evidence. It should show that what you expect to happen is actually happening. Every piece of evidence should answer a logically relevant question: What is this value at this point? Did something just complete successfully or not?


As it turns out, the problem wasn't in the file-copying, or even the loading of the file. The problem was in not using the resulting plist object correctly.

You should be able to design and write code that confirms the contents of a plist object. Knowing how to confirm things means you have to understand what things really are. If you don't really understand what things are, then you won't know what to confirm. The process of thinking about how to confirm something can lead you to a better understanding of what it is, or it can even correct a misunderstanding.


Code:
NSString *path = [[NSBundle mainBundle] pathForResource:@"EventAddress" ofType:@"plist"]; 
    NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
If that code works, then it suggests your plist file isn't what you originally posted. Your original post shows an Array containing two Strings.

If you only showed part of your plist, then the lesson is to use the entire plist, not just one part, and to post complete data, not just one part.

If you changed what's in your plist, then the lesson is to show what you changed.

There could be other reasons why that code works. It's impossible to say without seeing the complete plist data.

Code:
    NSArray* allmyKeys = [myDictionary  allValues];
The name of the variable allmyKeys is misleading. It actually holds all the values from the dictionary, not all the keys.

You should also read the reference doc on allValues, where it says "The order of the values in the array isn’t defined." This means you can't rely on a particular value being at index 0 in the returned NSArray. Which means that your code relying on things being at index 0 could fail unexpectedly.
 
Last edited:
Code:
    NSArray* allmyKeys = [myDictionary  allValues];
The name of the variable allmyKeys is misleading. It actually holds all the values from the dictionary, not all the keys.

You should also read the reference doc on allValues, where it says "The order of the values in the array isn’t defined." This means you can't rely on a particular value being at index 0 in the returned NSArray. Which means that your code relying on things being at index 0 could fail unexpectedly.

Wow, this is s a lengthy message. Sorry, I don't work over the weekends. So I did not see this post until today. Thanks for the info, unfortunately, I have to agree with you. I totally do not understand the plist thing. Will read your steps and try again hopefully I would understand the plist better. And you are right, its the allValues that made it work :)

And it may not be today or tomorrow, if I have anymore questions regarding the plist. Do I start a new topic or continue from here?
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.