11

I'm building an app which caches images in the Documents directory of the app bundle. In order to make sure the directories exist, I want to check to see if they exist and, if they don't, create them at the point at which the application starts.

Currently, I'm doing this in didFinishLaunchingWithOptions: like so:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    NSArray *directoriesToCreate = [[NSArray alloc] initWithObjects:
                                    @"DirA/DirA1",
                                    @"DirA/DirA2",
                                    @"DirB/DirB2",
                                    @"DirB/DirB2",
                                    @"DirC",
                                    nil];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsPath = [paths objectAtIndex:0];

    for (NSString *directoryToCreate in directoriesToCreate) {

        NSString *directoryPath = [documentsPath stringByAppendingPathComponent:directoryToCreate];
        NSLog(directoryPath);
        if (![[NSFileManager defaultManager] fileExistsAtPath:directoryPath isDirectory:YES]) {

            NSError *directoryCreateError = nil;
            [[NSFileManager defaultManager] createDirectoryAtPath:directoryPath
                                      withIntermediateDirectories:YES
                                                       attributes:nil
                                                            error:&directoryCreateError];


        }

    }

    [window addSubview:navigationController.view];
    [window makeKeyAndVisible];

    return YES;

}

On the very first run of the application – when none of the directories exist – the application runs, the directories are created as expected and everything runs just fine.

When the application is terminated, and runs again, I get an EXC_BAD_ACCESS signal on the fileExistsAtPath: call on [NSFileManager defaultManager].

What I don't understand is why this runs just fine when the directories don't exist, but it falls over when they do exist.

Can anyone offer any assistance?

abitgone
  • 561
  • 9
  • 29
  • Your NSLog should look like, `NSLog(@"%@", anObject);`. Specifying `NSLog(anObject);` works if *anObject* is a string, because a format string should be given in that place anyway. So, it will take *anObject* as the format string. But it will crash it is some other object than a string. – EmptyStack Jul 13 '11 at 13:21
  • Try to `retain` `paths` and `documentsPath` objects and `release` them after `for` cycle. – jamapag Jul 13 '11 at 13:23

2 Answers2

41

You're using the check function in the wrong way. 2nd parameter must be a pointer to a boolean variable which will be filled after function is called:

You are using function like this:

[[NSFileManager defaultManager] fileExistsAtPath:directoryPath isDirectory:YES];

But function should be used like this:

BOOL isDir;
[[NSFileManager defaultManager] fileExistsAtPath:directoryPath isDirectory:&isDir];

if (isDir) { // file exists and it is directory.
Eimantas
  • 48,927
  • 17
  • 132
  • 168
  • This explains why using the function without the `isDirectory` parameter works – thanks for explaining why. – abitgone Jul 13 '11 at 13:22
  • +1 And I really hate it that people don't care about compiler warnings. It points directly to the problem. – Eiko Jul 13 '11 at 13:24
  • I do care about compiler warnings – it's just that, in these very early stages of my tinkering with iOS, I don't often understand what they mean. – abitgone Jul 13 '11 at 13:28
  • @abitgone Yes, they can be difficult to understand - but it's really worth it. They are often the easiest way to fix problems, and to do so *early*. Here, the message tells you that the type of parameters doesn't match. – Eiko Jul 13 '11 at 14:13
  • 1
    I didn't get a compiler warning for this at all... would've saved me a lot of trouble! – Claudiu Sep 13 '13 at 17:40
5

isDirectory is a (BOOL*) for returning a boolean describing if the path points at a directory. You are passing a BOOL.

The reason it doesn't crash if the directory exists is that the value isn't set if the directory doesn't exist.

gaige
  • 17,263
  • 6
  • 57
  • 68
  • Changing `fileExistsAtPath:directoryPath isDirectory:YES` to just `fileExistsAtPath:directoryPath` seems to solve the issue. Thanks! – abitgone Jul 13 '11 at 13:20