Create folder/directory in Objective-C/cocoa

I have this code for creating a folder/directory in Objective-C/cocoa.

if(![fileManager fileExistsAtPath:directory isDirectory:&isDir])
        if(![fileManager createDirectoryAtPath:directory attributes:nil])
            NSLog(@"Error: Create folder failed %@", directory);

It works fine, but I got creatDirectoryAtPath:attributes is deprecated warning message. What's the newest way of making a directory builder in Cocoa/Objective-c?

SOLVED

BOOL isDir;
NSFileManager *fileManager= [NSFileManager defaultManager]; 
if(![fileManager fileExistsAtPath:directory isDirectory:&isDir])
    if(![fileManager createDirectoryAtPath:directory withIntermediateDirectories:YES attributes:nil error:NULL])
        NSLog(@"Error: Create folder failed %@", directory);

Found in the documentation:

-[NSFileManager createDirectoryAtPath:withIntermediateDirectories:attributes:error:]


Your solution is correct, though Apple includes an important note within NSFileManager.h:

/* The following methods are of limited utility. Attempting to predicate behavior 
based on the current state of the filesystem or a particular file on the 
filesystem is encouraging odd behavior in the face of filesystem race conditions. 
It's far better to attempt an operation (like loading a file or creating a 
directory) and handle the error gracefully than it is to try to figure out ahead 
of time whether the operation will succeed. */

- (BOOL)fileExistsAtPath:(NSString *)path;
- (BOOL)fileExistsAtPath:(NSString *)path isDirectory:(BOOL *)isDirectory;
- (BOOL)isReadableFileAtPath:(NSString *)path;
- (BOOL)isWritableFileAtPath:(NSString *)path;
- (BOOL)isExecutableFileAtPath:(NSString *)path;
- (BOOL)isDeletableFileAtPath:(NSString *)path;

Essentially, if multiple threads/processes are modifying the file system simultaneously the state could change in between calling fileExistsAtPath:isDirectory: and calling createDirectoryAtPath:withIntermediateDirectories:, so it is superfluous and possibly dangerous to call fileExistsAtPath:isDirectory: in this context.

For your needs and within the limited scope of your question it likely would not be a problem, but the following solution is both simpler and offers less of a chance of future issues arising:

NSFileManager *fileManager= [NSFileManager defaultManager];
NSError *error = nil;
if(![fileManager createDirectoryAtPath:directory withIntermediateDirectories:YES attributes:nil error:&error]) {
     // An error has occurred, do something to handle it
     NSLog(@"Failed to create directory \"%@\". Error: %@", directory, error);
}

Also note from Apple's documentation:

Return Value

YES if the directory was created, YES if createIntermediates is set and the directory already exists), or NO if an error occurred.

So, setting createIntermediates to YES, which you already do, is a de facto check of whether the directory already exists.


Thought I'd add to this and mention some more from the documentation about using the +defaultManager method:

In iOS and Mac OS X v 10.5 and later you should consider using [[NSFileManager alloc] init] rather than the singleton method defaultManager. Instances of NSFileManager are considered thread-safe when created using [[NSFileManager alloc] init].


You may prefer to work with the NSFileManager method:

createDirectoryAtURL:withIntermediateDirectories:attributes:error:

It works with URL's instead of path strings.