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

larswik

macrumors 68000
Original poster
Sep 8, 2006
1,552
11
I must be over looking something simple here Rob helped me earlier on this same project. My Dictionary is called 'skills' and I am just trying now to write the Dictionary to the Hard Drive using this code
Code:
   [skills writeToFile:@"/Users/test.plist" atomically:YES];

When I look in the users folder there is no test.plist file? I read the documentation and searched on line and followed the examples. WriteToFile is a method of NSMutableDictionary.

I am just storing information in the dictionary from 2 NSTextFields as the Object and Key With this code
Code:
[skills setObject:[skillBonusPrefField stringValue] forKey:[skillNamePref stringValue]];

There must be a simple answers why I can't see the file, I hope
 
Code:
   [skills writeToFile:@"/Users/test.plist" atomically:YES];

You'll find this call is failing and returning NO because users can't write to the /Users directory. Try writing into your subdirectory under /Users. For example, @"/Users/Lars/test.plist".
 
Yep, that was it. Thanks Jim. What if I give a version to a friend to try out? It will be looking for my name 'Lars'. Is there a common folder that I can put it in. I am guessing there is a way to bypass the username to add it to the Documents folder.

This will keel me moving forward for now.

Thanks again.
 
Yep, that was it. Thanks Jim. What if I give a version to a friend to try out? It will be looking for my name 'Lars'. Is there a common folder that I can put it in. I am guessing there is a way to bypass the username to add it to the Documents folder.

This will keel me moving forward for now.

Thanks again.

The are few techniques you can use.

The easiest is to use NSString's stringByExpandingTildeInPath which will expand ~ into the full path to the user's home directory.
Code:
NSString* fullPath = [@"~/test.plist" stringByExpandingTildeInPath];
[skills writeToFile:fullPath atomically:YES];

There are other techniques for find specific directories, such as the user's documents directory. See Creating Paths and Locating Directories.
 
Cool, I will read up on the stringByExpandingTildeInPath in the morning and add it in. I got a lot done today.

Thanks for the help!
 
Thanks for the tip regarding the 'stringByExpandingTildeInPath'. It worked and I added the word Documents to the list so it writes it in the Documents folder. I am getting an error when I try to write to that file later in the program when I try to add something, I get 'EXC Bad Access" error message. When the program starts it checks for the file at that path, if not found it writes a blank plist file. I can look in the folder and I can see that it is created with this code
Code:
-(void)loadPrefsAtStart{
    skills = [[NSMutableDictionary alloc] init]; // Instansitates the NSMutableDictionary
    filemgr = [NSFileManager defaultManager];
    fileSavePath = [@"~/Documents/XPCalc.plist" stringByExpandingTildeInPath]; // Sets up the default path to the file.
    
    if ([filemgr fileExistsAtPath: fileSavePath ] == YES){
        skills = [[NSMutableDictionary alloc] initWithContentsOfFile: fileSavePath]; // it reads the file into the Dictionary
        for (NSString *i in skills) {         //  for loop to loop through the keys if the Dictionary and add to popUpButton
            [popUpButtonDisplay addItemWithTitle: i];
        }
    }
    else {
        [skills writeToFile: fileSavePath atomically:YES]; // if it can't find it, it writes a blank file.
    }
    
    [doaPrefField setStringValue:[ prefs stringForKey: @"doaPrefSave"]]; // reads in the NSUserDefault pref.
}
That code works fine and creates the file. When they add a new item to the list it should save it, but I get the error message on the last line of code bellow.

Code:
- (IBAction)addSkillPrefButton:(id)sender {
   [popUpButtonDisplay addItemWithTitle: [skillNamePref stringValue]]; // adds item to popUpbutton display
   [skills setObject:[skillBonusPrefField stringValue] forKey:[skillNamePref stringValue]]; // adds obj and key to the NSMutDict
   [skillNamePref setStringValue:@"-"]; //resets textfield
   [skillBonusPrefField setStringValue:@"-"]; //resets textfield
   [skills writeToFile: fileSavePath atomically: YES]; // saves the file by writing it to disk
    }

I am lost because it writes it the first time to that location if the file does not exist so why could I not write over it with new data? Unless I need to append that file?
 
I am lost because it writes it the first time to that location if the file does not exist so why could I not write over it with new data?

I haven't read the thread in detail so could be way off base, but often when this happens it's because the file is left open for read in another part of the code.

B
 
I will look at that. I am also looking to see if I have some kind of memory management issue. I have never worked with the NSFileManager before I am not sure if I need to retain that object I create to keep writing or reading from that file.

My gut says Memory Management.
 
balamw - I worked through the problem. You were right, about it being open. I made the mistake of putting this [filemgr release]; in the dealloc method. My thinking was that I would need to access the file all the time so keep it alive.

I also need to add this code
Code:
filemgr = [NSFileManager defaultManager];
   fileSavePath = [@"~/Documents/XPCalc.plist" stringByExpandingTildeInPath]; // Sets up the default path to the file.
To my addSkills button method. The help I got yesterday from Rob helped me better understand Memory Management and allowed me, with your hint , to fix the problem and see what is happening.

Thanks!
 
The really kosher way to form you file save path is:
Code:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSAssert([paths count] > 0, @"Failed to find the user's document directory");
NSString *documentsPath = [paths objectAtIndex:0];
fileSavePath = [documentsPath stringByAppendingPathComponent:@"XPCalc.plist"];
 
Last edited:
That almost look confusing? Why would you put a pointer to a path inside of an NSArray? NSAssert, I have not seen that yet. This line I understand 'NSString *documentsPath = [paths objectAtIndex:0];' but why it is looking into the first index in an array I don't get. Why not store the path in an NSString? The last part I learned today and understand :)
 
That almost look confusing? Why would you put a pointer to a path inside of an NSArray? NSAssert, I have not seen that yet. This line I understand 'NSString *documentsPath = [paths objectAtIndex:0];' but why it is looking into the first index in an array I don't get. Why not store the path in an NSString? The last part I learned today and understand :)

It's possible for NSSearchPathForDirectoriesInDomains to return multiple paths, that's why it returns an array. It's unlikely in this case that NSSearchPathForDirectoriesInDomains will return more than one path, and it would be unclear what to do if it did return multiple paths, so the code just uses the first path.

But happens if NSSearchPathForDirectoriesInDomains returns no paths at all, either returning nil or an empty array? The code assumes (or asserts) that this will not happen, so NSAssert checks for that.

Basically NSAssert will evaluate the expression in the first parameter. If it is true, all is good, and the good continues. If it is false, then something is wrong, and NSAssert raises an exception containing the string in the second parameter.

NSAssert is a good technique for defensive, fast-fail programming. You can read more about NSAssert in the Assertions and Logging Programming Guide.
 
The more I am getting into Objective-C and Cocoa I can see it is not a hobby for people. You really need to apply yourself and take it seriously if you are going to learn. I'm lucky because I work for myself and I can spend more time on this then most people. But wow, a lot to learn.

Thanks, as always.
 
Programming is my hobby. But I've got almost a couple of decades of experience to back it up.

Slowly slowly you'll get exposed to all the pieces.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.