I have a Swift program that helps organise cat shows. It generates several rtf files and an xml file, which should be saved into one folder on disk, and only have minor modifications to their file names - the first one could be named 'Cat show.rtf', then the next 'Cat show judges.rtf', and the next 'Cat show.xml'.
I would like to only display one NSSavePanel to locate the folder to save the files in, rather than keep popping up a save panel for each file.
I tried using a NSSavePanel to get a URL for the first file, and then modifying that URL for each subsequent file. The first file was saved, but each following file got a 'Operation not permitted' error and was not saved. I tried using NSSavePanel to get the folder to save the files in, but got a 'Operation not permitted' error for all of the files. I could just use NSSavePanel to get the URL for each file individually, but would rather not do that as it will confuse the users.
Does anyone have any idea how I can do this?
The code I use to change the URL is:
func newURL(from oldURL : URL, with newName: String) -> URL {
return oldURL.deletingLastPathComponent().appendingPathComponent(newName)
}
let challengesURL = newURL(from: url, with: "\(name).xml")
OK, I have confirmed what is happening here. First of all you need to have the AppSandbox enabled and the file access permissioned to allow read/write for the User Selected File. I have noted how to do this in the comments below, but as you are able to save the user selected file name I propose this is OK.
In short, the NSSavePanel only returns a Security Scoped URL for the filename entered, not the directory. As such you can save that file many times but not adjust the filename (as it is a new URL without permissions). A possible work around and how I had previously saved multiple files is to use an NSOpenPanel which allows the user to select a directory. This returns a Security Scoped directory url so you have permission to the directory within the scope. This allows you to save multiple files in that directory.
In the code below I have put the two solutions that demonstrate this and you can see with the NSSavePanel, it saves the entered filename twice with amended contents but does not write the programmatically amended filename. By using the NSOpenPanel to select a directory, and collect the filename from the user in a text field, all files are saved fine.
Hope this helps.
The NSSavePanel and NSOpenPanel documentation confirm the Security Scope of the returned urls. There is some ability to save security scoped NSURL bookmarks but I have not used this previously. There are details on bookmarks in the documentation here. It seems an extra level of complexity.
https://developer.apple.com/documentation/foundation/nsurl
You could look in to adding application entitlements to particular directories, but as you seem to want the the user to select anywhere they want to save the Panel approach is the way to go as wide open entitlements are not recommended.
https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/AppSandboxTemporaryExceptionEntitlements.html#//apple_ref/doc/uid/TP40011195-CH5-SW7