I'm adapting my App (OSX, XCode 8.3) to sandbox.
I've created the entitlements for the app.
I'm locked at the first step of writing a file.
In the basic version, I do so :
IBAction is called by menu item
@IBAction func newDossier(_ sender: NSMenuItem) {
let savePanel = NSSavePanel()
savePanel.title = "List file"
savePanel.prompt = "Create"
let fileManager = FileManager.default
savePanel.begin() { (result) -> Void in
if (result == NSFileHandlingPanelOKButton) {
let fileWithExtensionURL = savePanel.url!.appendingPathExtension("xxxx") // I call the file Theleme and select Desktop as location
if fileManager.fileExists(atPath: fileWithExtensionURL.path) {
// warning that file did exist already
} else {
// fileWithExtensionURL is written to a global var
globalURL = fileWithExtensionURL
let _ = writeAFile
}
}
}
}
func writeAFile() -> Bool {
let url = globalURL // fileWithExtensionURL from the NSSavePanel, stored in a global
let data = NSMutableData()
let archiver = NSKeyedArchiver(forWritingWith: data)
// Call archiver.encode() with data to save
archiver.finishEncoding()
data.write(to: globalURL, atomically: true)
}
return true
}My issue is this : when I do this with sandboxing enabled (entitlements), the file is not written.
I understand I need to use bookmarks instead of URL, but where and how ?
I have tried just to create a bookmark in writeAFile, but even this doesn't work : I get a message of non existing file :
Error Domain=NSCocoaErrorDomain Code=260 "Scoped bookmarks can only be created for existing files or directories" UserInfo={NSURL=file:/ / / Users/me/Desktop/Theleme.xxxx NSDebugDescription=Scoped bookmarks can only be created for existing files or directories}
func writeAFile() -> Bool {
let url = globalURL // fileWithExtensionURL from the NSSavePanel, stored in a global
let data = NSMutableData()
let archiver = NSKeyedArchiver(forWritingWith: data)
// Call archiver.encode() with data to save
archiver.finishEncoding()
data.write(to: globalURL, atomically: true)
// 27.7.2017 Creating bookmarks for sandboxing
do {
let bookmark = try globalURL!bookmarkData(options: [.withSecurityScope], includingResourceValuesForKeys: nil, relativeTo: nil)
Swift.print(bookmark)
} catch {
Swift.print(error)
}
}
return true
}
I moved one inch forward ! Writing file to the container :
let documentsUrl = FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask)[0] as URL // or .documents
let fileName = globalURL!.deletingPathExtension().lastPathComponent
let fileUrl = documentsUrl.appendingPathComponent(fileName)
let result = data.write(to: fileUrl, atomically: true) /I have now 2 questions :
- here I write to the desktopDirectory ; how to replace by a directory selected by user in NSSavePanel ?
- the documents are "hidden" in the Library/Containers/com.xxxx.App/Data/Desktop/ ;
is it possible to get the files visible directly in the directory selected by user ?
So that he can later copy and paste those files and reuse the copy in the App ? Or launch App by double clicking the file icon.