Reputation: 1213
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];
Upvotes: 73
Views: 79701
Reputation: 1
(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
Upvotes: 0
Reputation: 23053
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)
}
Upvotes: 172
Reputation: 19
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");
}
Upvotes: 1
Reputation: 51
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");
}
Upvotes: 4
Reputation: 639
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)")
Upvotes: 0
Reputation: 10299
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
}()
Upvotes: 1
Reputation: 5569
"~/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}
}
Upvotes: 1
Reputation: 1161
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)")
}
Upvotes: 70
Reputation: 34513
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)")
}
}
Upvotes: 5