Sandbox is really very strict. You are in the sandbox, you cannot play outside without authorization. You have a local desktop inside the sandbox, but the one of the yard !
So, you need first to authorize access, then save to the selected folder.
I ended up with the following scheme to create a file in an outside folder:
- openPanel first, to declare a folder to authorize
- I inform user about this
- in its completion, call savePanel.
Here it is, for an action called from a menuItem:
@IBAction func newDossier(_ sender: NSMenuItem) {
let openPanel = NSOpenPanel() // Authorize access in sandboxed mode
openPanel.message = NSLocalizedString("Select folder where to create file\n(Necessary to manage security on this computer)", comment: "enableFileMenuItems")
openPanel.prompt = NSLocalizedString("Select", comment: "enableFileMenuItems")
openPanel.canChooseFiles = false // Only select or create Directory here ; you can select the real Desktop
openPanel.canChooseDirectories = true
openPanel.canCreateDirectories = true
openPanel.begin() { // In the completion, Save the file
(result2) -> Void in
if result2 == NSApplication.ModalResponse.OK {
storeBookmark(url: openPanel.url!) // Save the bookmark for future use if needed
let savePanel = NSSavePanel()
savePanel.title = NSLocalizedString("File to create", comment: "enableFileMenuItems")
savePanel.nameFieldStringValue = ""
savePanel.prompt = NSLocalizedString("Create", comment: "enableFileMenuItems")
savePanel.allowedFileTypes = ["xxxx"] // if you want to specify file signature
let fileManager = FileManager.default
savePanel.begin() { (result) -> Void in
if result == NSApplication.ModalResponse.OK {
let fileWithExtensionURL = savePanel.url! // May test that file does not exist already
if fileManager.fileExists(atPath: fileWithExtensionURL.path) {
} else {
// Now, write the file
}
}
}
}
}
}