Creating a directory at /Users/Shared/ - using Swift - swift

I am using the following code to create a directory in /Users/Shared/ to share data of my application between all users. When i run the code gotthe below output.
2019-03-08 19:41:41.751418+0530 MyApp[7224:488397] Couldn't create document directory
2019-03-08 19:41:41.754026+0530 MyApp[7224:488397] Document directory is file:///Users/Appname
let fileManager = FileManager.default
if let tDocumentDirectory = fileManager.urls(for: .userDirectory, in: .localDomainMask).first {
let filePath = tDocumentDirectory.appendingPathComponent("Appname")
if !fileManager.fileExists(atPath: filePath.path) {
do {
try fileManager.createDirectory(atPath: filePath.path, withIntermediateDirectories: true, attributes: nil)
} catch {
NSLog("Couldn't create document directory")
}
}
NSLog("Document directory is \(filePath)")
}
I don't why this error occured. How this can be done?

Please read the log messages carefully.
You are trying to create the folder file:///Users/Appname which is not in /Users/Shared. You have to append "Shared/Appname".
And you are encouraged to use the URL related API of FileManager (and less confusing variable names šŸ˜‰)
let fileManager = FileManager.default
let userDirectory = try! fileManager.url (for: .userDirectory, in: .localDomainMask, appropriateFor: nil, create: false)
let folderURL = userDirectory.appendingPathComponent("Shared/Appname")
if !fileManager.fileExists(atPath: folderURL.path) {
do {
try fileManager.createDirectory(at: folderURL, withIntermediateDirectories: true, attributes: nil)
} catch {
print("Couldn't create document directory", error)
}
}
print("Document directory is \(folderURL)")

Related

FileManager doesn't have permission to access Music directory [duplicate]

This question already has answers here:
NSFileManager.defaultManager().fileExistsAtPath returns false instead of true
(2 answers)
Closed 8 months ago.
I want to create one folder in the fileManager root path, but before creating it, I want to check that the folder exist or not, and if not, I will create, otherwise will leave it
here are the function that I use
public func isDirectoryExist(path: String) -> Bool {
let fileManager = FileManager.default
var isDir : ObjCBool = false
if fileManager.fileExists(atPath: path, isDirectory:&isDir) {
if isDir.boolValue {
return true
} else {
return false
}
} else {
return false
}
}
public func createNewDirectory(name: String) {
let DocumentDirectory = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])
let DirPath = DocumentDirectory.appendingPathComponent(name)
do
{
try FileManager.default.createDirectory(atPath: DirPath!.path, withIntermediateDirectories: true, attributes: nil)
}
catch let error as NSError
{
Logger.logError("Unable to create directory \(error.debugDescription)")
}
Logger.logInfo("Dir Path = \(DirPath!)")
}
Now, when I check the folder existing, it's always false and create a new folder and it happen every time
func createARObjectDirectory() {
let rootURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
if isDirectoryExist(path: "\(rootURL.absoluteString)\(DefaultURL.arObjectUrlDirectoryName)") {
Logger.logServer("ARObject directly found")
} else {
createNewDirectory(name: DefaultURL.arObjectUrlDirectoryName)
}
}
Then I print the root url, and seems the hash in the middle of url is always different, how I can check it?
file:///var/mobile/Containers/Data/Application/5AD0690B-498D-4309-8BD0-191FB88766AC/Documents/AR-Object/
file:///var/mobile/Containers/Data/Application/41D35A54-1807-417E-AE29-311D43FCC21D/Documents/AR-Object/
file:///var/mobile/Containers/Data/Application/F7E385CC-7921-4C37-B9BF-BCEFFC2AEE9E/Documents/AR-Object/
file:///var/mobile/Containers/Data/Application/4748B014-5E55-46BB-BC83-394A6BC27292/Documents/AR-Object/
Thanks for your help
You are using the wrong API. absoluteString (in rootURL.absoluteString) returns the string representation including the scheme file://. The correct API for file system URLs is path
I recommend to use the URL related API as much as possible
public func directoryExists(at url: URL) -> Bool {
let fileManager = FileManager.default
var isDir : ObjCBool = false
if fileManager.fileExists(atPath: url.path, isDirectory:&isDir) {
return isDir.boolValue
} else {
return false
}
}
and compose the URL in a more reliable way
func createARObjectDirectory() {
let rootURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
if directoryExists(at: rootURL.appendingPathComponent(DefaultURL.arObjectUrlDirectoryName) {
Logger.logServer("ARObject directly found")
} else {
createNewDirectory(name: DefaultURL.arObjectUrlDirectoryName)
}
}
And this is swiftier too
public func createNewDirectory(name: String) {
let documentDirectory = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let dirURL = documentDirectory.appendingPathComponent(name)
do
{
try FileManager.default.createDirectory(at: dirURL, withIntermediateDirectories: false, attributes: nil)
}
catch let error as NSError
{
Logger.logError("Unable to create directory \(error.debugDescription)")
}
Logger.logInfo("Dir Path = \(dirPath.path)")
}
The actual path to your app's documents directory is subject to change. You should use relative paths from the documents directory, and not try to compare paths between runs.
(I believe the path changes each time you rebuild your app or reinstall it, but is {fairly} stable for app store builds.)
Are you saying that the directory you create inside the documents directory goes away between runs? That should not be true. The contents of the documents directory should persist.

Different path URL for FileManager everytime I open the app [duplicate]

This question already has answers here:
NSFileManager.defaultManager().fileExistsAtPath returns false instead of true
(2 answers)
Closed 8 months ago.
I want to create one folder in the fileManager root path, but before creating it, I want to check that the folder exist or not, and if not, I will create, otherwise will leave it
here are the function that I use
public func isDirectoryExist(path: String) -> Bool {
let fileManager = FileManager.default
var isDir : ObjCBool = false
if fileManager.fileExists(atPath: path, isDirectory:&isDir) {
if isDir.boolValue {
return true
} else {
return false
}
} else {
return false
}
}
public func createNewDirectory(name: String) {
let DocumentDirectory = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])
let DirPath = DocumentDirectory.appendingPathComponent(name)
do
{
try FileManager.default.createDirectory(atPath: DirPath!.path, withIntermediateDirectories: true, attributes: nil)
}
catch let error as NSError
{
Logger.logError("Unable to create directory \(error.debugDescription)")
}
Logger.logInfo("Dir Path = \(DirPath!)")
}
Now, when I check the folder existing, it's always false and create a new folder and it happen every time
func createARObjectDirectory() {
let rootURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
if isDirectoryExist(path: "\(rootURL.absoluteString)\(DefaultURL.arObjectUrlDirectoryName)") {
Logger.logServer("ARObject directly found")
} else {
createNewDirectory(name: DefaultURL.arObjectUrlDirectoryName)
}
}
Then I print the root url, and seems the hash in the middle of url is always different, how I can check it?
file:///var/mobile/Containers/Data/Application/5AD0690B-498D-4309-8BD0-191FB88766AC/Documents/AR-Object/
file:///var/mobile/Containers/Data/Application/41D35A54-1807-417E-AE29-311D43FCC21D/Documents/AR-Object/
file:///var/mobile/Containers/Data/Application/F7E385CC-7921-4C37-B9BF-BCEFFC2AEE9E/Documents/AR-Object/
file:///var/mobile/Containers/Data/Application/4748B014-5E55-46BB-BC83-394A6BC27292/Documents/AR-Object/
Thanks for your help
You are using the wrong API. absoluteString (in rootURL.absoluteString) returns the string representation including the scheme file://. The correct API for file system URLs is path
I recommend to use the URL related API as much as possible
public func directoryExists(at url: URL) -> Bool {
let fileManager = FileManager.default
var isDir : ObjCBool = false
if fileManager.fileExists(atPath: url.path, isDirectory:&isDir) {
return isDir.boolValue
} else {
return false
}
}
and compose the URL in a more reliable way
func createARObjectDirectory() {
let rootURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
if directoryExists(at: rootURL.appendingPathComponent(DefaultURL.arObjectUrlDirectoryName) {
Logger.logServer("ARObject directly found")
} else {
createNewDirectory(name: DefaultURL.arObjectUrlDirectoryName)
}
}
And this is swiftier too
public func createNewDirectory(name: String) {
let documentDirectory = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let dirURL = documentDirectory.appendingPathComponent(name)
do
{
try FileManager.default.createDirectory(at: dirURL, withIntermediateDirectories: false, attributes: nil)
}
catch let error as NSError
{
Logger.logError("Unable to create directory \(error.debugDescription)")
}
Logger.logInfo("Dir Path = \(dirPath.path)")
}
The actual path to your app's documents directory is subject to change. You should use relative paths from the documents directory, and not try to compare paths between runs.
(I believe the path changes each time you rebuild your app or reinstall it, but is {fairly} stable for app store builds.)
Are you saying that the directory you create inside the documents directory goes away between runs? That should not be true. The contents of the documents directory should persist.

Unable to save multiple text files in same folder (MacOS Swift Application)

I am trying to save multiple text files in the same folder. So far I can save one text file into a generated folder in my document directory, but I cannot save more than one text file in that same folder.
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
let docURL = URL(string: documentsDirectory)!
let dataPath = docURL.appendingPathComponent("User_Notes")
// this is the folder name
if !FileManager.default.fileExists(atPath: dataPath.path) {
do {
try
FileManager.default.createDirectory(atPath: dataPath.path, withIntermediateDirectories: true, attributes: nil)
// try stringToWrite.write(to: &dataPath)
try stringToWrite.write(toFile: "\(dataPath)/\(userNotes)).txt", atomically: true, encoding: String.Encoding.utf8)
} catch {
print(error.localizedDescription)
}
}
if error != nil {
print("Error saving user data.")
}
}

Write a bundle as a file

I want to write a bundle I've dragged and dropped into my project folder into a temporary file.
Previously I used fileManager.copyItem but it deleted the original.
Original code
func copyPackagedBundleToDocuments(withDestinationName dest: String) {
if let bundlePath = Bundle.main.path(forResource: embeddedBundle, ofType: nil) {
let fileManager = FileManager.default
let destPath = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!
// applicationSupportDirectory is not created by default in the sandbox, and therefore we need to make sure that it exists!
let urls = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask)
if let applicationSupportURL = urls.last {
do {
try fileManager.createDirectory(at: applicationSupportURL, withIntermediateDirectories: true, attributes: nil)
} catch {
print(error)
}
}
let fullDestPath = NSURL(fileURLWithPath: destPath + "/" + dest)
do {
try fileManager.copyItem(atPath: bundlePath, toPath: fullDestPath.path!)
} catch {
print(error)
}
}
}
This tells me the paths etc. are fine, since it does copy the file.
Now I want an atomic copy, so want to use Data(contentsOfFile)
So I rewrote everything:
func copyPackagedBundleToDocuments(withDestinationName dest: String) {
if let bundlePath = Bundle.main.path(forResource: embeddedBundle, ofType: nil) {
let fileManager = FileManager.default
let destPath = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!
// applicationSupportDirectory is not created by default in the sandbox, and therefore we need to make sure that it exists!
let urls = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask)
if let applicationSupportURL = urls.last {
do {
try fileManager.createDirectory(at: applicationSupportURL, withIntermediateDirectories: true, attributes: nil)
} catch {
print(error)
}
}
let urlPath = URL(fileURLWithPath: destPath + "/" + dest)
let dta = try? Data(contentsOf: URL(fileURLWithPath: bundlePath) )
do {
try dta.write(to: urlPath , options: .atomic)
} catch {
print ("error \(error)")
}
}
}
However the data (dta) here is nil!
I think this is because my bundle location (as follows) ends in a backslash /:
file:///Users/user/Library/Developer/CoreSimulator/Devices/37A85B0B-F2B7-4A0C-BAA7-E05A831FFAE0/data/Containers/Bundle/Application/AD665103-E256-4F6C-8248-B62D8FF9FDC8/LocalBundle.app/Bundle.bundle/
and I guess that copyItem can treat the bundle as a single file, but writing the bundle to data is somehow not possible (the path is correct, since the code using copyItem works).
For clarity the following
if let bundleURL = Bundle.main.url(forResource: embeddedBundle, withExtension: nil) {
print ( try? Data(contentsOf: bundleURL ) )
}
prints nil to the console, validating the url for the bundle.
How can I write my bundle to a file, atomically?

iOS9 Swift File Creating NSFileManager.createDirectoryAtPath with NSURL

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"}}
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/
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)")
}
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)")
}