Search code examples
iosobjective-ccocoa-touchplistnsfilemanager

unable to write to a file in AplicationSupport directory


I am trying to store some values in a plist in the Application support directory of my iOS app. But the write always fails. I used boiler plate code from iOS documentation.

In the code below I always hit an error while doing writeToURL:atomically. I.E I always get a "Failed to write to plist" in the log and the file is never created.

The URL appears to be created correctly. This is what I see in the URL print below. URL to store plist is file:///var/mobile/Containers/Data/Application/9E26C447-7562-438E-A38A-E8F04C6DAFFE/Library/Application%20Support/com.apm.smartiothome.chatime/bcastSeqNum.plist

I would appreciate any pointers on what Im doing wrong.

 NSFileManager* sharedFM = [NSFileManager defaultManager];
NSArray* possibleURLs = [sharedFM URLsForDirectory:NSApplicationSupportDirectory
                                         inDomains:NSUserDomainMask];
NSURL* appSupportDir = nil;
NSURL* appDirectory = nil;

if ([possibleURLs count] >= 1) {
    // Use the first directory (if multiple are returned)
    appSupportDir = [possibleURLs objectAtIndex:0];
}

// If a valid app support directory exists, add the
// app's bundle ID to it to specify the final directory.
if (appSupportDir)
{
    NSString* appBundleID = [[NSBundle mainBundle] bundleIdentifier];
    appDirectory = [appSupportDir URLByAppendingPathComponent:appBundleID];
}
else
{
    DDLogError(@"Could not get pointer to app support directory") ;
}

self.bcastSeqNumFilePtr = [appSupportRootPtr URLByAppendingPathComponent:@"bcastSeqNum.plist" isDirectory:NO];

NSMutableArray *arrToReturn ;

arrToReturn = [NSMutableArray arrayWithContentsOfURL:self.bcastSeqNumFilePtr] ;

if(!arrToReturn)
{
    /*File does not exist...create one*/
    DDLogVerbose(@"Bcast seq num file does not exist.  Creating bcast plist file") ;
    NSMutableDictionary *dictToStore = [[NSMutableDictionary alloc] init] ;
    NSMutableArray *arrToReturn = [[NSMutableArray alloc] init] ;
    [arrToReturn addObject:[NSNumber numberWithInt:-1]] ;
    [dictToStore setObject:arrToReturn forKey:@"Bcast Seq Numbers"] ;
    if(![dictToStore writeToURL:self.bcastSeqNumFilePtr atomically:YES])
    {
        DDLogError(@"Failed to write to plist.") ;
    }
}
else
{
    DDLogVerbose(@"Bcase seq num file exists. returning seq number list from it %@",arrToReturn) ;
}

Solution

  • The problem is that writeToURL will not create any missing directories in the path for you. If you call:

    NSError *error;
    [sharedFM createDirectoryAtURL:appDirectory withIntermediateDirectories:NO attributes:nil error:&error];
    

    this will create the directory.

    One question, why are you adding the bundleIdentifier into the path? The app support directory you get is already private to your app's sandbox. If you don't add this then you don't need to create the directory.