create plist and copy it to folder MacOS Swift - swift

I have been racking my brain on how to create and write a plist to a certain Folder Directory in MacOS. In my case to the LaunchDaemons folder in /Library. I know how to create the plist but its the writing to the LaunchDaemons folder that I am having issues with. This code below from my understanding is for the sandbox but how do I do it outside of the sandbox? Cheers
let fileManager = FileManager.default
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let path = documentDirectory.appending("test.plist")
I have added the code with the help I have received and have no errors but it is not writing anything to the folder. Here is the code:
let libraryDirectory = try! FileManager.default.url(for: .libraryDirectory, in: .localDomainMask, appropriateFor: nil, create: false)
let launchDaemonsFolder = libraryDirectory.appendingPathComponent("LaunchDaemons/test.plist")
if FileManager.default.fileExists(atPath: launchDaemonsFolder.path) {
print(launchDaemonsFolder)
let plistDictionary : [String: Any] = [
"ExitTimeOut": 600,
"Label": "BOOT.SHUTDOWN.SERVICE",
"ProgramArguments": ["/test.sh"] as Array,
"RunAtLoad": false,
"WorkingDirectory": "/"
]
let dictionaryResult = NSDictionary(dictionary: plistDictionary)
let fileWritten = dictionaryResult.write(to: launchDaemonsFolder, atomically: true)
print("is the file created: \(fileWritten)")
} else {
print("File Exists")
}

First of all NSSearchPathForDirectoriesInDomains is outdated, it's highly recommended to use the URL related API anyway.
This code creates an URL pointing to /Library/LaunchDaemons
let libraryDirectory = try! FileManager.default.url(for: .libraryDirectory, in: .localDomainMask, appropriateFor: nil, create: false)
let launchDaemonsFolder = libraryDirectory.appendingPathComponent("LaunchDaemons")

Related

Swift Filemanager fails to create temporary directory

This Code:
let csvString = self.generateCSV()
let tmpURL = try FileManager.default.url(for: .itemReplacementDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: true)
let tempFileUrl = tmpURL.appendingPathComponent("App-DigiAufklaerung-\(self.formatDateToPrecision(Date())).csv")
let data = csvString.data(using: .utf8)
try data?.write(to: tempFileUrl,
options: .atomic)
self.csvFile = tempFileUrl
(I thought) should create a tmp file, from which i can then share the cdv through AirDrop, but the creation of the tmpDir fails, what am i doing wrong here?
This error message was printed several times:
CFURLSetTemporaryResourcePropertyForKey failed because it was passed an URL which has no scheme

How create folder in documents app in iPhone folder

How can im create folder in documents app.
Im tried this:
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory: String = paths.first ?? ""
let dataPath = documentsDirectory + "/yourFolderName"
if !FileManager.default.fileExists(atPath: dataPath) {
try? FileManager.default.createDirectory(atPath: dataPath, withIntermediateDirectories: false, attributes: nil)
}
Example:
Folder inside iPhone folder:

swift save file after download Alamofire

download and save file
let destination: DownloadRequest.DownloadFileDestination = { _, _ in
// var fileURL = self.createFolder(folderName: downloadFolderName)
var fileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let fileName = URL(string : currentFile.link )
fileURL = fileURL.appendingPathComponent((fileName?.lastPathComponent)!)
return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
}
Alamofire.download(currentDownloadedFile.link , to: destination).response(completionHandler: { (DefaultDownloadResponse) in
print("res ",DefaultDownloadResponse.destinationURL!);
completion(true)
})
but when i wont to check file in this dirrectory i get nil
let filemanager:FileManager = FileManager()
let fileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let files = filemanager.enumerator(atPath: fileURL.absoluteString) // = nil
while let file = files?.nextObject() {
print(file)
}
if i save local path to file and after reload app wont to share it -> "share" app cant send file (mb cant found it)
can u pls help me. how it works ? why when i print all files he didnt find it? how to save file who after reboot app it will be saved in same link
You are using the wrong API
For file system URLs use always path, absoluteString returns the full string including the scheme (e. g. file:// or http://)
let files = filemanager.enumerator(atPath: fileURL.path)

How can I find the path of iOS app internal directory in Swift?

How can I find the path of iOS app internal directory in Swift?
Firstly, what is the equivalent name of android app internal directory in iOS app?
Secondly, how can I find the path of the directory?
which api should I use in Swift?
My main purpose is trying to copy Bundle sqlite file to the directory
To get path of document directory you can use this code.
// path to documents directory
let documentDirectoryPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first
if let documentDirectoryPath = documentDirectoryPath {
}
For more information follow these links : File System Basics and Accessing Files and Directories
Try this -
public func getDatabasePath() -> String {
let databaseURL = try? FileManager.default
.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
.appendingPathComponent("YOUR_DB_FILE_NAME.sqlite")
// If DB file not present in file manager copy DB file to user document directory
let fileManager = FileManager.default
if fileManager.fileExists(atPath: (databaseURL?.path)!) {
print("FILE AVAILABLE")
return (databaseURL?.path)!
} else {
print("FILE NOT AVAILABLE ... Copying")
if fileManager.createFile(atPath: (databaseURL?.path)!, contents: Data(), attributes: nil) {
return (databaseURL?.path)!
}
}
return ""
}

Swift 4 alternative if let

I have this code, it checks if a file exists in the document directory, if it does it used this to set up the data for the controller, if it doesn't it uses a file supplier in the bundle, and if also that fails it set up an empty view controller.
Is there a way to conditionally set the url variable so that I can write the parse(fromFile:) method once instead of in an if else? The most intuitive way would appear to be if let url = something || let url = somethingElse then perform in the parse(fromFile: url) in the brackets, but it appears that it's not possible with swift.
if let url = try? FileManager().url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: true).appendingPathComponent("database.json") {
parse(fromFile: url)
} else if let url = Bundle.main.url(forResource: "database", withExtension: "json") {
parse(fromFile: url)
} else {
setUpWithNothing()
}
I would recommend to split the code into several steps:
let documentsUrl = try! FileManager.default.url(
for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: true
)
The documents directory should always exists therefore I am not too worried about using try!. However, if you worry, you should solve that special case separately, e.g. using:
guard let documentUrl = try? ... else {
setUpWithNothing()
return
}
Then:
let fileUrl = documentUrl.appendingPathComponent("database.json")
This call never fails, it doesn't check the existence of the file. You need to check existence explicitly:
let fileExists = FileManager.default.fileExists(atPath: fileUrl.path)
let defaultUrl = Bundle.main.url(forResource: "database", withExtension: "json")
let databaseUrl = fileExists ? fileUrl : defaultUrl!
Again, you shouldn't worry about the existence of the file in your bundle, if you know it's there and simply call:
parse(fromFile: databaseUrl)
However, if you want to be extra careful, just remove the ! and use:
if let databaseUrl = fileExists ? fileUrl : defaultUrl {
parse(fromFile: databaseUrl)
} else {
setUpWithNothing()
}
You can use the nil-coalescing operator (??):
If the expression with FileManager returns nil (by throwing, thanks to the try?), then Bundle.main.url(...) will be used instead.
If that is also nil, then the conditional binding will fail entirely, and the else block will be run setUpWithNothing().
if let url = (try? FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: true
).appendingPathComponent("database.json"))
?? Bundle.main.url(forResource: "database", withExtension: "json") {
parse(fromFile: url)
} else {
setUpWithNothing()
}
Since you're doing the same thing in the first two cases and something different in the second, this is a good candidate for it's own function:
func databaseFileURL() -> URL? {
if let url = try? FileManager().url(for: .documentDirectory, in: .userDomainMask,
appropriateFor: nil, create: true) {
return url.appendingPathComponent("database.json")
}
else {
return Bundle.main.url(forResource: "database", withExtension: "json")
}
}
and then you can just do
if let url = databaseFileURL() {
parse(fromFile: url)
} else {
setUpWithNothing()
}
It nicely separates concerns and makes it cleaner and clearer at the point of use. And if you need to do anything else with the file you can just call the function rather than copy-pasting the logic.