89

I'm trying to understand how to use the function fileExistsAtPath:isDirectory: with Swift but I get completely lost.

This is my code example:

var b:CMutablePointer<ObjCBool>?

if (fileManager.fileExistsAtPath(fullPath, isDirectory:b! )){
    // how can I use the "b" variable?!
    fileManager.createDirectoryAtURL(dirURL, withIntermediateDirectories: false, attributes: nil, error: nil)
}

I can't understand how can I access the value for the b MutablePointer. What If I want to know if it set to YES or NO?

MatterGoal
  • 16,038
  • 19
  • 109
  • 186

5 Answers5

189

The second parameter has the type UnsafeMutablePointer<ObjCBool>, which means that you have to pass the address of an ObjCBool variable. Example:

var isDir : ObjCBool = false
if fileManager.fileExistsAtPath(fullPath, isDirectory:&isDir) {
    if isDir {
        // file exists and is a directory
    } else {
        // file exists and is not a directory
    }
} else {
    // file does not exist
}

Update for Swift 3 and Swift 4:

let fileManager = FileManager.default
var isDir : ObjCBool = false
if fileManager.fileExists(atPath: fullPath, isDirectory:&isDir) {
    if isDir.boolValue {
        // file exists and is a directory
    } else {
        // file exists and is not a directory
    }
} else {
    // file does not exist
}
OhadM
  • 4,687
  • 1
  • 47
  • 57
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • 1
    Here is the link to the doc, https://developer.apple.com/documentation/foundation/filemanager/1410277-fileexists# – XY L Jan 24 '18 at 08:54
  • 26
    This is one of the weirdest interfaces I have ever seen. Why couldn't there just be a isDirectory(path:) function? – quemeful Aug 28 '18 at 12:12
  • @quemeful I just added an answer below that makes this API more natural for Swift users: https://stackoverflow.com/a/70759674/3451975 – Jeehut Jan 18 '22 at 17:16
15

Tried to improve the other answer to make it easier to use.

enum Filestatus {
        case isFile
        case isDir
        case isNot
}
extension URL {
    
    
    var filestatus: Filestatus {
        get {
            let filestatus: Filestatus
            var isDir: ObjCBool = false
            if FileManager.default.fileExists(atPath: self.path, isDirectory: &isDir) {
                if isDir.boolValue {
                    // file exists and is a directory
                    filestatus = .isDir
                }
                else {
                    // file exists and is not a directory
                    filestatus = .isFile
                }
            }
            else {
                // file does not exist
                filestatus = .isNot
            }
            return filestatus
        }
    }
}
Meep
  • 501
  • 6
  • 24
Jonny
  • 15,955
  • 18
  • 111
  • 232
8

I've just added a simple extension to FileManager to make this a bit neater. Might be helpful?

extension FileManager {
    
    func directoryExists(_ atPath: String) -> Bool {
        var isDirectory: ObjCBool = false
        let exists = fileExists(atPath: atPath, isDirectory:&isDirectory)
        return exists && isDirectory.boolValue
    }
}
Nicolas Miari
  • 16,006
  • 8
  • 81
  • 189
Karl Nosworthy
  • 1,991
  • 1
  • 17
  • 16
8

Just to overload the bases. Here is mine that takes a URL

extension FileManager {

    func directoryExists(atUrl url: URL) -> Bool {
        var isDirectory: ObjCBool = false
        let exists = self.fileExists(atPath: url.path, isDirectory:&isDirectory)
        return exists && isDirectory.boolValue
    }
}
ziligy
  • 1,447
  • 16
  • 10
1

I wrote this small FileManager extension which makes this call more Swifty:

extension FileManager {
  /// Checks if a file or folder at the given URL exists and if it is a directory or a file.
  /// - Parameter path: The path to check.
  /// - Returns: A tuple with the first ``Bool`` representing if the path exists and the second ``Bool`` representing if the found is a directory (`true`) or not (`false`).
  func fileExistsAndIsDirectory(atPath path: String) -> (Bool, Bool) {
    var fileIsDirectory: ObjCBool = false
    let fileExists = FileManager.default.fileExists(atPath: path, isDirectory: &fileIsDirectory)
    return (fileExists, fileIsDirectory.boolValue)
  }
}

Usage is like this:

let filePath = "/Users/Me/Desktop/SomeDirectory"
let (fileExists, fileIsDirectory) = FileManager.default.fileExistsAndIsDirectory(atPath: filePath)
// -> (true: something exists at this path, true: the thing is a directory)
Jeehut
  • 20,202
  • 8
  • 59
  • 80