The NSOpenSavePanelDelegate `validate` delegate method does not receive permission to the selected directory/file in sandboxed app
Originator: | sindresorhus | ||
Number: | rdar://46998451 | Date Originated: | 02-Jan-2019 11:51 AM |
Status: | Open | Resolved: | |
Product: | macOS + SDK | Product Version: | macOS 10.14.2 |
Classification: | Other Bug | Reproducible: | Always |
Summary: I use `NSOpenPanel` to let the user select a directory where my app can output some files. I want to inform the user early, while the open panel is still open, if the user tries to select a read-only directory, as I wouldn't be able to write to that. The problem is that the `validate` delegate method doesn't get access to the user-selected directory, so it will always show the error message for all directories, even writable ones. Steps to Reproduce: I have this code to open the panel: ```swift @NSApplicationMain final class AppDelegate: NSObject, NSApplicationDelegate { func convert() { let panel = NSOpenPanel() panel.delegate = self panel.canChooseFiles = false panel.canChooseDirectories = true panel.canCreateDirectories = true panel.allowsMultipleSelection = false panel.prompt = "Convert" panel.message = "Choose where to save the converted images" panel.beginSheetModal(for: window) { if $0 == .OK { self.startConversion(urls, outputDirectory: panel.urls.first!) } } } } ``` And I have implemented the `validate` delegate method to show an error while the open panel is shown, which informs the user that the directory they chose is read-only: ```swift extension AppDelegate: NSOpenSavePanelDelegate { func panel(_ sender: Any, validate url: URL) throws { if !FileManager.default.isWritableFile(atPath: url.path) { throw CocoaError(.fileWriteVolumeReadOnly) } } } ``` Expected Results: I expected `FileManager.default.isWritableFile(atPath: url.path)` to return `true` for a path that is writable. Actual Results: The code `FileManager.default.isWritableFile(atPath: url.path)` always returns `false` because it doesn't get access to the security scoped bookmark created by `NSOpenPanel`. Version: macOS 10.14.2 Notes: The workaround is to just let the user select anything, then in `panel.beginSheetModal`, check whether the directory writable, and if not, show an NSAlert and then show the `NSOpenPanel` again. This is a bad user-experience.
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!
Stack Overflow question
https://stackoverflow.com/questions/6844383/nssavepanel-and-the-sandbox
Related Radar
https://openradar.appspot.com/radar?id=4931161214156800
Twitter thread
https://twitter.com/sindresorhus/status/1080417460359176192