iOS9 Swift File Creating NSFileManager.createDirectoryAtPath with NSURL

24,365

Solution 1

I figured this one out. createDirectoryAtPath() is unable to process a path with the "file://" prefix. To get a path without the prefix you must use path() or relativePath().

let documentsPath = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0])
let logsPath = documentsPath.URLByAppendingPathComponent("logs")
do {
    try NSFileManager.defaultManager().createDirectoryAtPath(logsPath.path!, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
    NSLog("Unable to create directory \(error.debugDescription)")
}

Incorrect path (notice file://):

file:///var/mobile/Containers/Data/Application/F2EF2D4F-94AF-4BF2-AF9E-D0ECBC8637E7/Documents/logs/

Correct path:

/var/mobile/Containers/Data/Application/F2EF2D4F-94AF-4BF2-AF9E-D0ECBC8637E7/Documents/logs/

Solution 2

Swift 3

let documentsPath = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])
let logsPath = documentsPath.appendingPathComponent("logs")
do {
    try FileManager.default.createDirectory(at: logsPath!, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
    NSLog("Unable to create directory \(error.debugDescription)")
}

Solution 3

Swift 4

let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let logsPath = paths[0].appendingPathComponent("logs")
do {
    try FileManager.default.createDirectory(at: logsPath, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
    NSLog("Unable to create directory \(error.debugDescription)")
}
Share:
24,365
Moemars
Author by

Moemars

Dev hacking away with Java and Ruby working for Mobile Advertising company Thinknear.

Updated on January 20, 2020

Comments

  • Moemars
    Moemars over 4 years

    Before iOS9, we had created a directory like so

    let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! String
    let logsPath = documentsPath.stringByAppendingPathComponent("logs")
    let errorPointer = NSErrorPointer()
    NSFileManager.defaultManager().createDirectoryAtPath(logsPath, withIntermediateDirectories: true, attributes: nil, error: errorPointer)
    

    But with iOS9 they removed String.stringByAppendingPathComponent. The auto convert tool replaced our use of String with NSURL. createDirectoryAtPath() takes a string so I need to convert the NSURL to a string. We used absolutePath like so: (update for iOS9)

    let documentsPath = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0])
    let logsPath = documentsPath.URLByAppendingPathComponent("logs")
    do {
        try NSFileManager.defaultManager().createDirectoryAtPath(logsPath.absoluteString, withIntermediateDirectories: true, attributes: nil)
    } catch let error as NSError {
        NSLog("Unable to create directory \(error.debugDescription)")
    }
    

    But I am getting the following error:

    Unable to create directory Error Domain=NSCocoaErrorDomain Code=513 "You don’t have permission to save the file “logs” in the folder “Documents”." UserInfo={NSFilePath=file:///var/mobile/Containers/Data/Application/F2EF2D4F-94AF-4BF2-AF9E-D0ECBC8637E7/Documents/logs/, NSUnderlyingError=0x15664d070 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}

  • App Dev Guy
    App Dev Guy over 6 years
    relativePath is the winner. I had .absoluteString but seems like that is long since outdated.