0

So I'm trying to store some data between openings of an app I'm making, but for some reason the directory I'm making and the data I'm storing aren't persisting between app openings, and I can't figure out why…

I have three methods:

- (NSString *)pathForDataFile 
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask,     YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    documentsDirectory = [documentsDirectory stringByAppendingPathComponent:@"MyApp"];
    NSLog(@"%@", documentsDirectory);

    NSError *error;
    NSLog(@"%i", (int)[[NSFileManager defaultManager] createDirectoryAtPath:documentsDirectory withIntermediateDirectories:YES attributes:nil error:&error]);   

    return documentsDirectory;
}

- (void)saveDataToDisk 
{
    NSString * path = [self pathForDataFile];

    NSMutableDictionary * rootObject;
    rootObject = [NSMutableDictionary dictionary];

    [rootObject setValue: [self usedPlaces] forKey:@"key"];
    [NSKeyedArchiver archiveRootObject: rootObject toFile: path];
}

- (void) loadDataFromDisk
{
    NSString     * path = [self pathForDataFile];
    NSDictionary * rootObject;

    rootObject = [NSKeyedUnarchiver unarchiveObjectWithFile:path];    
    [self setObject: [rootObject valueForKey:@"key"]];
}

When I print out the result of creating the directory in pathForDataFile, every time it prints 1, which means every time it's creating that directory, even though it shouldn't be able to since the directory should already exist after one call. saveDataToDisk is called in applicationWillTerminate, and loadDataFromDisk is called in applicationDidBecomeActive. Can anybody help me as to why this is happening?

Michael Dautermann
  • 88,797
  • 17
  • 166
  • 215
The Awesome Guy
  • 322
  • 5
  • 15
  • 1
    applicationWillTerminate may not give you enough time. could you call that method from somewhere else for testing purpose? – Warif Akhand Rishi Jun 11 '12 at 04:04
  • @WarifAkhandRishi The thing is though that it IS printing out the `NSLog()`s, so that means the method is being called in time and it's not an issue of timing... – The Awesome Guy Jun 11 '12 at 22:39

1 Answers1

0

You need to do some additional error checking in your code to try to narrow down where the problem is actually happening.

Error checking like the new lines in your original sample code:

- (NSString *)pathForDataFile 
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    documentsDirectory = [documentsDirectory stringByAppendingPathComponent:@"MyApp"];
    BOOL success = [[NSFileManager defaultManager] createDirectoryAtPath:documentsDirectory withIntermediateDirectories:YES attributes:nil error:&error];
    // success is NO only if there is an error.  success is YES if directory was created or if the directory already exists
    if(success == NO)
    {
        NSLog( @"error creating directory at path %@ is %@", documentsDirectory, [error localizedDescription] );
    }

    return documentsDirectory;
}

- (void)saveDataToDisk 
{
    NSString * path = [self pathForDataFile];
    if(([self usedPlaces] == NULL) || ([self usedPlaces count] == 0))
    {
        NSLog( @"usedPlaces is either null or has no entries");
    }
    NSDictionary * rootObject = [NSDictionary dictionaryWithObject: [self usedPlaces] forKey: @"key"];
    BOOL success = [NSKeyedArchiver archiveRootObject: rootObject toFile: path];
    if(success == NO)
    {
        NSLog( @"was not able to write data to path %@", path );
    }
}

- (void) loadDataFromDisk
{
    NSString     * path = [self pathForDataFile];
    NSDictionary * rootObject;

    rootObject = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
    if(rootObject)
        [self setObject: [rootObject valueForKey:@"key"]];
    else
        NSLog( @"was not able to load data from file at %@", path );
}
Michael Dautermann
  • 88,797
  • 17
  • 166
  • 215
  • I used these error checks, and these lines are what was output (each method output one error, and the errors are in the order that the methods are in above) `was not able to load data from file at /var/mobile/Applications/B2D28246-F274-4789-9976-178EF6F649CC/Library/MyApp` `was not able to write data to path /var/mobile/Applications/B2D28246-F274-4789-9976-178EF6F649CC/Library/MyApp` `was not able to load data from file at /var/mobile/Applications/B2D28246-F274-4789-9976-178EF6F649CC/Library/MyApp` EDIT: sorry for the bad formatting, idk how to fix this... – The Awesome Guy Jun 11 '12 at 22:24
  • So it looks like something about your "`NSKeyedArchiver`" call in "`saveDataToDisk`" is failing. My guess is that one of the objects in your "`usedPlaces`" property is not one that can be easily archived. You need to make sure *everything* in that array / dictionary can be saved to disk (i.e. and conforms to the NSCoding protocol). [Check out this Apple article on encoding & decoding objects](http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Archiving/Articles/codingobjects.html#//apple_ref/doc/uid/20000948-BCIHBJDE). – Michael Dautermann Jun 12 '12 at 02:46