How to check if a directory exists in Objective-C

33,112

Solution 1

Take a look in the documentation for this method signature:

- (BOOL)fileExistsAtPath:(NSString *)path isDirectory:(BOOL *)isDirectory

You need a pointer to a BOOL var as argument, not a BOOL itself. NSFileManager will record if the file is a directory or not in that variable. For example:

BOOL isDir;
BOOL exists = [fm fileExistsAtPath:path isDirectory:&isDir];
if (exists) {
    /* file exists */
    if (isDir) {
        /* file is a directory */
    }
 }

Solution 2

Just in case somebody needs a getter, that creates a folder in Documents, if it doesn't exist:

- (NSString *)folderPath
{
    if (! _folderPath) {
        NSString *folderName = @"YourFolderName";
        NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectoryPath = [documentPaths objectAtIndex:0];
        _folderPath = [documentsDirectoryPath stringByAppendingPathComponent:folderName];

        // if folder doesn't exist, create it
        NSError *error = nil;
        NSFileManager *fileManager = [NSFileManager defaultManager];
        BOOL isDir;
        if (! [fileManager fileExistsAtPath:_folderPath isDirectory:&isDir]) {
            BOOL success = [fileManager createDirectoryAtPath:_folderPath withIntermediateDirectories:NO attributes:nil error:&error];
            if (!success || error) {
                NSLog(@"Error: %@", [error localizedDescription]);
            }
            NSAssert(success, @"Failed to create folder at path:%@", _folderPath);
        }
    }

    return _folderPath;
}

Solution 3

I have a Utility singleton class that I use for things like this. Since I can’t update my database if it remains in Documents, I copy my .sqlite files from Documents to /Library/Private Documents using this code. The first method finds the Library. The second creates the Private Documents folder if it doesn’t exist and returns the location as a string. The second method uses the same file manager method that @wzboson used.

+ (NSString *)applicationLibraryDirectory {

            return [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
}


+ (NSString *)applicationLibraryPrivateDocumentsDirectory {

    NSError *error;
    NSString *PrivateDocumentsDirectory = [[self applicationLibraryDirectory] stringByAppendingPathComponent:@"Private Documents"];

    BOOL isDir;
    if (! [[NSFileManager defaultManager] fileExistsAtPath:PrivateDocumentsDirectory isDirectory:&isDir]) {

        if (![[NSFileManager defaultManager] createDirectoryAtPath:PrivateDocumentsDirectory
                                       withIntermediateDirectories:NO
                                                        attributes:nil
                                                             error:&error]) {
            NSLog(@"Create directory error: %@", error);
        }
    }

    return PrivateDocumentsDirectory;
}

I use it like this in my persistent store coordinator initialization. The same principal applies to any files though.

NSString *libraryDirectory = [Utilities applicationLibraryPrivateDocumentsDirectory];
NSString *sourcePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:sqliteName];
NSString *destinationPath = [libraryDirectory stringByAppendingPathComponent:sqliteName];
Share:
33,112

Related videos on Youtube

n.evermind
Author by

n.evermind

I speak: Copy-and-paste, Basic, Objective-C, Python, Django and have recently learned how to use the very retro but stylish terminal. Otherwise: Creator of digital-analog-but-stunningly beautiful notebooks in love with beautiful UIs

Updated on October 10, 2020

Comments

  • n.evermind
    n.evermind over 3 years

    I guess this is a beginner's problem, but I was trying to check if a directory exists in my Documents folder on the iPhone. I read the documentation and came up with this code which unfortunately crashed with EXC_BAD_ACCESS in the BOOL fileExists line:

     -(void)checkIfDirectoryAlreadyExists:(NSString *)name
    {
        NSFileManager *fileManager = [[NSFileManager alloc] init];
    
        NSString *path = [[self documentsDirectory] stringByAppendingPathComponent:name];
    
        BOOL fileExists = [fileManager fileExistsAtPath:path isDirectory:YES];
    
        if (fileExists)
        {
            NSLog(@"Folder already exists...");
        }
    
    }
    

    I don't understand what I've done wrong? It looks all perfect to me and it certainly complies with the docs, not? Any revelations as to where I went wrong would be highly appreciated! Thanks.

    UPDATED:

    Still not working...

      -(void)checkIfDirectoryAlreadyExists:(NSString *)name
    {
        NSFileManager *fileManager = [[NSFileManager alloc] init];
    
        NSString *path = [[self documentsDirectory] stringByAppendingPathComponent:name];
    
        BOOL isDir;
        BOOL fileExists = [fileManager fileExistsAtPath:path isDirectory:&isDir];
    
        if (fileExists)
        {
    
    
            if (isDir) {
    
                NSLog(@"Folder already exists...");
    
            }
    
        }
    
    }
    
    • n.evermind
      n.evermind over 12 years
      @Legolas it checks if it is a directory according to the docs. But I guess this is where I went wrong.
    • EricLeaf
      EricLeaf over 12 years
      The second is not working in what sense, still a bad access? Also wanted to point out, from the docs: Note: Attempting to predicate behavior based on the current state of the file system or a particular file on the file system is not recommended. Doing so can cause odd behavior or race conditions. It's far better to attempt an operation (such as loading a file or creating a directory), check for errors, and handle those errors gracefully than it is to try to figure out ahead of time whether the operation will succeed.
  • n.evermind
    n.evermind over 12 years
    thanks so much. I think apple should put your example in their docs- I didn't understand them, but now they are clear - through your example! Thanks again, really appreciated.
  • n.evermind
    n.evermind over 12 years
    Actually, just tried to implement this, but it still crashed my app. I updated the code above. Any ideas? Thanks for your help.
  • sidyll
    sidyll over 12 years
    @n.evermind: glad to help. Yes, examples are important but may take too much space :-) don't worry, you'll end up accustomed with extracting the exact information from the documentation. Also, note that Apple gave an example for this method which touches the directory part. Back to the problem, I can't see errors here, apart for the unusual way of creating the file manager object (didn't notice it before). Do you have any special reason not to use [NSFileManager defaultManager]? It may save you some trouble.
  • sidyll
    sidyll over 12 years
    @n.evermind It should work anyway. Try placing a break point right before BOOL isDir; line, and once the program stops there type po path in your debugger. Does it print the correct value?
  • EricLeaf
    EricLeaf over 12 years
    @sidyll Good point, especially since in this case it would prevent the memory leak.