Is there a safer way to create a directory if it does not exist?

IosObjective CFilesystemsNsfilemanagerNsdocumentdirectory

Ios Problem Overview


I've found this way of creating a directory if it does not exist. But it looks a bit wonky and I am afraid that this can go wrong in 1 of 1000 attempts.

if(![[NSFileManager defaultManager] fileExistsAtPath:bundlePath]) {
    [[NSFileManager defaultManager] createDirectoryAtPath:bundlePath withIntermediateDirectories:YES attributes:nil error:NULL];
}

There is only this awkward method fileExistsAtPath which also looks for files and not only directories. But for me, the dangerous thing is: What if this goes wrong? What shall I do? What is best practice to guarantee that the directory is created, and only created when it does not exist?

I know file system operations are never safe. Device could loose battery power suddenly just in the moment where it began shoveling the bits from A to B. Or it can stumble upon a bad bit and hang for a second. Maybe in some seldom cases it returns YES even if there is no directory. Simply put: I don't trust file system operations.

How can I make this absolutely safe?

Ios Solutions


Solution 1 - Ios

You can actually skip the if, even though Apple's docs say that the directory must not exist, that is only true if you are passing withIntermediateDirectories:NO

That puts it down to one call. The next step is to capture any errors:

NSError * error = nil;
[[NSFileManager defaultManager] createDirectoryAtPath:bundlePath
                          withIntermediateDirectories:YES
                                           attributes:nil
                                                error:&error];
if (error != nil) {
    NSLog(@"error creating directory: %@", error);
    //..
}

This will not result in an error if the directory already exists.

Solution 2 - Ios

For Swift 3.0

do {
    try FileManager.default.createDirectory(atPath: folder, withIntermediateDirectories: true, attributes: nil)
} catch {
    print(error)
}

Solution 3 - Ios

Swift 4.2

let fileManager = FileManager.default
let documentsURL =  fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!

let imagesPath = documentsURL.appendingPathComponent("Images")
do
{
    try FileManager.default.createDirectory(atPath: imagesPath.path, withIntermediateDirectories: true, attributes: nil)
}
catch let error as NSError
{
    NSLog("Unable to create directory \(error.debugDescription)")
}

Solution 4 - Ios

Swift 5.0

let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
let docURL = URL(string: documentsDirectory)!
let dataPath = docURL.appendingPathComponent("MyFolder")
if !FileManager.default.fileExists(atPath: dataPath.absoluteString) {
    do {
        try FileManager.default.createDirectory(atPath: dataPath.absoluteString, withIntermediateDirectories: true, attributes: nil)
    } catch {
        print(error.localizedDescription);
    }
}

Solution 5 - Ios

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);

From an SO topic here.

After creating a directory, you can flush the file system then check to see if your newly created directory exists. This is probably overkill, but you can never have too much overkill.

Solution 6 - Ios

In swift 2 it looks like this:

do {
    try NSFileManager.defaultManager().createDirectoryAtPath(pathURL.absoluteString, withIntermediateDirectories: true, attributes: nil)
} catch {
    print(error)
}

Solution 7 - Ios

Useful if the path is like - /folder/image.png

    let pathComponents = path.components(separatedBy: "/").dropLast()
    var directoryPath: String = ""
    for component in pathComponents {
        directoryPath += component + "/"
    }
    do {
        try FileManager.default.createDirectory(atPath: directoryPath, withIntermediateDirectories: true, attributes: nil)
    } catch {
        print(error)
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondontWatchMyProfileView Question on Stackoverflow
Solution 1 - Iose.JamesView Answer on Stackoverflow
Solution 2 - IosSergey NikitinView Answer on Stackoverflow
Solution 3 - IosAbhishek JainView Answer on Stackoverflow
Solution 4 - IosVed SharmaView Answer on Stackoverflow
Solution 5 - IosCharles BurnsView Answer on Stackoverflow
Solution 6 - IosChrisView Answer on Stackoverflow
Solution 7 - IosEvgeniyView Answer on Stackoverflow