71

I'm having some trouble with converting Objective-C code to create a directory for Swift.

Objective-C:

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
    NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"/MyFolder"];

    if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
    [[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error];
Kampai
  • 22,848
  • 21
  • 95
  • 95
Gian
  • 1,193
  • 2
  • 8
  • 20
  • 3
    Show us what you tried in Swift, and what is that it's not working. – Danny S Nov 14 '14 at 13:48
  • 2
    I think it is a bit rude to ask for what OP tried in Swift, because the question is clear enough as it is for anyone who is familiar with Swift and willing to help. – Totoro Jun 20 '20 at 04:42

9 Answers9

170

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.path) {
    do {
        try FileManager.default.createDirectory(atPath: dataPath.path, withIntermediateDirectories: true, attributes: nil)
    } catch {
        print(error.localizedDescription)
    }
}

Swift 4.0

let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let documentsDirectory: AnyObject = paths[0] as AnyObject
let dataPath = documentsDirectory.appendingPathComponent("MyFolder")!
    
do {
    try FileManager.default.createDirectory(atPath: dataPath.absoluteString, withIntermediateDirectories: false, attributes: nil)
} catch let error as NSError {
    print(error.localizedDescription)
}

Swift 3.0

let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let documentsDirectory: AnyObject = paths[0]
let dataPath = documentsDirectory.appendingPathComponent("MyFolder")!
        
do {
    try FileManager.default.createDirectory(atPath: dataPath.absoluteString, withIntermediateDirectories: false, attributes: nil)
} catch let error as NSError {
    print(error.localizedDescription)
}

Swift 2.1

You can create directory using below method:

let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
let documentsDirectory: AnyObject = paths[0]
let dataPath = documentsDirectory.stringByAppendingPathComponent("MyFolder")

do {
    try NSFileManager.defaultManager().createDirectoryAtPath(dataPath, withIntermediateDirectories: false, attributes: nil)
} catch let error as NSError {
    print(error.localizedDescription)
}
Kampai
  • 22,848
  • 21
  • 95
  • 95
70

None of @Kampai and @Crashalot's answers worked for me.

The .absoluteString makes a url with file:// prefix and it cause exception while creating directory. Instead I've used .path method.

The fixed code for Swift 3

let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let dataPath = documentsDirectory.appendingPathComponent("MyFolder")

do {
    try FileManager.default.createDirectory(atPath: dataPath.path, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
    print("Error creating directory: \(error.localizedDescription)")
}
Mehdi Hosseinzadeh
  • 1,160
  • 11
  • 25
5

The accepted answer no longer compiles as the line with appendingPathComponent generates an error.

Here's a Swift 3 version that compiles:

fileprivate func createDir(dirName: String) {
    let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let dataPath = documentsDirectory.appendingPathComponent(dirName)

    do {
        try FileManager.default.createDirectory(atPath: dataPath.absoluteString, withIntermediateDirectories: false, attributes: nil)
    } catch let error as NSError {
        printError("Error creating directory: \(error.localizedDescription)")
    }
}
Crashalot
  • 33,605
  • 61
  • 269
  • 439
  • 1
    I did try this on an iPhone but i could not find the created folder in the device. Have updated the device to iOS 11, which has the files App. – Suhail Parvez Feb 05 '18 at 16:31
4

Swift 4 :

NSSearchPathForDirectoriesInDomains returns an array of strings, not URLs.

appendingPathComponent to string makes app crash with the message -[NSPathStore2 URLByAppendingPathComponent:]: unrecognized selector sent to instance

Here's a Swift 4 version that compiles:

    let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
    if let pathURL = URL.init(string: paths[0]) {
        let dataURL = pathURL.appendingPathComponent("MyFolder")
        do {
            try FileManager.default.createDirectory(atPath: dataURL.absoluteString, withIntermediateDirectories: true, attributes: nil)
        } catch let error as NSError {
            print(error.localizedDescription);
        }
    }
    else {
        print("Error in getting path URL");
    }
1

Simpler solution:

"~/Desktop/demo".expand.createDir()//Now you have a folder named demo on your desk

extension String{
    func createDir(_ path:String){
        do {
            try FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
        } catch let error as NSError {
            NSLog("Unable to create directory \(error.debugDescription)")
        }
    }
    var expand:String {return NSString(string: self).expandingTildeInPath}
}
Sentry.co
  • 5,355
  • 43
  • 38
1

Swift 4

// DB Directory and Path
lazy var applicationDocumentsDirectory: URL = {

    let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    let documentDirectoryURL = urls[urls.count - 1] as URL
    let dbDirectoryURL = documentDirectoryURL.appendingPathComponent("DB")

    if FileManager.default.fileExists(atPath: dbDirectoryURL.path) == false{
        do{
            try FileManager.default.createDirectory(at: dbDirectoryURL, withIntermediateDirectories: false, attributes: nil)
        }catch{
        }
    }
    return dbDirectoryURL
}()
Gurjinder Singh
  • 9,221
  • 1
  • 66
  • 58
1

Swift 5

guard let path = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first else { return }
    if let pathURL = URL.init(string: path) {
        let dataURL = pathURL.appendingPathComponent("MyFolderName")
        do {
            try FileManager.default.createDirectory(atPath: dataURL.absoluteString, withIntermediateDirectories: true, attributes: nil)
        } catch let error as NSError {
            print(error.localizedDescription);
        }
    }
    else {
        print("Error in URL path");
    }
Praveen
  • 19
  • 1
  • 5
0

For Other developers, Im gonna leave this here as it may help someone like me looking for a way to figure out where the folder is being created.

let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
let documentsDir = paths.firstObject as String
println("Path to the Documents directory\n\(documentsDir)")
bona912
  • 589
  • 2
  • 6
  • 14
0
(lldb) p path.absoluteString
(String) $R23 = "file:///Users/vincent/Library/Developer/CoreSimulator/Devices/4778E487-D1AD-41E7-9B91-18E08A400DEA/data/Containers/Data/Application/286AF87C-1134-4308-9656-DEE8F9FF046E/Documents/tide/927EBC30-EAD1-44BA-80B2-FD3D0A66E9DE"
(lldb) p path.path
(String) $R25 = "/Users/vincent/Library/Developer/CoreSimulator/Devices/4778E487-D1AD-41E7-9B91-18E08A400DEA/data/Containers/Data/Application/286AF87C-1134-4308-9656-DEE8F9FF046E/Documents/tide/927EBC30-EAD1-44BA-80B2-FD3D0A66E9DE"
(lldb) 

so if you receive

Error Domain=NSCocoaErrorDomain Code=642 "You can’t save the file “927EBC30-EAD1-44BA-80B2-FD3D0A66E9DE” because the volume is read only." UserInfo={NSFilePath=file:///Users/vincent/Library/Developer/CoreSimulator/Devices/4778E487-D1AD-41E7-9B91-18E08A400DEA/data/Containers/Data/Application/286AF87C-1134-4308-9656-DEE8F9FF046E/Documents/tide/927EBC30-EAD1-44BA-80B2-FD3D0A66E9DE, NSUnderlyingError=0x6000009cccf0 {Error Domain=NSPOSIXErrorDomain Code=30 "Read-only file system"}}

you need

path.absoluteString => path.path
HeminWon
  • 1
  • 1
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 10 '22 at 17:46