1

User has to save a file, but I only want them saving the file in one folder. How to do this?

I have already tried implementing the delegate and forcefully setting back the directory if it is different. This does not work. The user is still able to select other folders when the save panel opens

extension Project:  NSOpenSavePanelDelegate  {
    func panel(_ sender: Any, didChangeToDirectoryURL url: URL?) {
        if url != testsFolder {
            (sender as! NSSavePanel).directoryURL = testsFolder
        }
    }

    func panel(_ sender: Any, validate url: URL) throws {
        if url.deletingLastPathComponent() != testsFolder {
            (sender as! NSSavePanel).directoryURL = testsFolder
            throw ProjectError.scriptInitiliation
        }
    }
}
swift nub
  • 2,747
  • 3
  • 17
  • 39
  • Please describe "does not work". Does the app crash? Are the delegate methods called? – Willeke Oct 25 '19 at 08:59
  • It does not crash. But the user is still able to select other folders when the save panel opens. – swift nub Oct 25 '19 at 09:20
  • 1
    Ask the user once to open the requested folder, add a security scoped bookmark and then ask the user only for the file name. – vadian Oct 25 '19 at 09:39
  • @vadian ..this seems more like a work around. The thing is, the folder is already fix fixed within the app. Asking the user to open might be a bad experience. I just wanted the SavePannel to open so that the user can enter a filename so that the file can be saved. If user enters an already existing file, the NSSavePanel already handles this. I just do not want the user to change folders, because it is fixed. (unless i mistook what you said?) – swift nub Oct 25 '19 at 13:36
  • 1
    If the app is sandboxed – what it seems to be – there are two scenarios: 1) Save the file inside the application container and ask the user only for the file name. 2) For any (fixed) folder outside of the container you need to ask the user to open the folder once to create a security scoped bookmark. – vadian Oct 25 '19 at 14:25
  • ok.. i guess those are the only options? It is not a sandboxed app (and cannot be one), and I only wanted the NSSavePanel to present the user a common interface that they are used to. If there is no way configure the NSSavePanel itself (and not a workaround) so that it behaves like what i described above, then I think I might have to do something else. Thanks for letting me know. – swift nub Oct 25 '19 at 16:49

1 Answers1

1

The thing is, the folder is already fix fixed within the app.

This is the time to acquire permission from the user to access this folder. Use a open (not save) dialog to have the user confirm selection of the folder. Think of this as a "confirm access dialog", you can:

  • Change the label of the "Open" button to something else using prompt
  • Set the title and message so the dialog is clearly a confirmation dialog
  • set the initial folder using directoryURL to the parent of the one you want confirmed (Note: any changes to directoryURL after the dialog is up are ignored so you cannot lock the dialog to that folder using the delegate didChangeToDirectoryURL – in the early sandbox you could but Apple has now stopped that)
  • Set the delegate and use its shouldEnable and validate callbacks to make sure only the folder you wish to have confirmed can be selected or the dialog cancelled.
  • Set canCreateDirectories & canChooseFiles to false, canChooseDirectories to true

Once the user has confirmed the folder access save a security scoped bookmark in your app's prefs. Your app can now regain access to that folder at any time. With that permission you can create and open files and folders within that folder without using NSOpenPanel or NSSavePanel again.

From this point to restrict users to saving in that folder put up your own dialog to ask for just the filename, omitting the path part, and bypass NSSavePanel –you can impersonate the standard dialogs or design your own from scratch.

HTH

CRD
  • 52,522
  • 5
  • 70
  • 86