views:

2831

answers:

1

Hi there,

I seem to have stumbled over a problem regarding saving an xml file from a string (this is done on the iPhone) The file itself exists and included in the project (hence within the workspace), and all indications I get from the code snippet which follows passes without any errors on the emulator and fail on the iPhone (error 513), but in either case the file is not saved!

{
Hits = config->Hits;

NSString*   filenameStr = [m_FileName stringByAppendingFormat: @".xml" ]; 
NSString*   pData = [self getDataString];  // write xml format - checked out ok
NSError     *error;

/* option 2 - does not work as well
 NSBundle        *mainBundle = [NSBundle mainBundle];
 NSURL           *xmlURL = [NSURL fileURLWithPath:[mainBundle pathForResource: m_FileName ofType: @"xml"]];

 if(![pData writeToURL: xmlURL atomically: true encoding:NSUTF8StringEncoding error:&error]) 
 {
 NSLog(@"Houston - we have a problem %s@\n",[error localizedFailureReason]);
 return false;
 }
 */

if(![pData writeToFile: filenameStr atomically: FALSE encoding:NSUTF8StringEncoding error:&error]) 
{
    NSLog(@"Houston - we have a problem %s@\n",[error localizedFailureReason]);
    return false;
}
return true;

}

Any help would be appreciated, -A

+9  A: 

You should not write to files included in the application package. On a real iPhone, you may be prevented from doing this because these files are digitally signed.

Even if you can modify a packaged file, it is not a good place to store data. Re-installing the application from an App Store upgrade or an Xcode build will overwrite the file with the original.

Instead, store your XML into the Documents directory. You can get the path like this:

NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, 
    NSUserDomainMask, YES); 
NSString* documentsDirectory = [paths objectAtIndex:0];     
NSString* leafname = [m_FileName stringByAppendingFormat: @".xml" ]; 
NSString* filenameStr = [documentsDirectory
    stringByAppendingPathComponent:leafname];

If your file needs some initial state that you don't want to generate in your code, have your app check that it is present in the documents directory the first time it is needed and, if it is missing, copy it from the template in the package.

An alternative to storing structured data is to use user defaults. For example:

[[NSUserDefaults standardUserDefaults] setObject:foo forKey:FOO_KEY];
Will Harris
+1 for the user defaults approach. However, the file doesn't prevent overwriting because it's digitally signed, but rather that it's read-only and can't be overwritten. They are digitally signed as well, but this isn't what prevents it from being written to.
AlBlue