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

Stack Overflow question

https://stackoverflow.com/questions/6844383/nssavepanel-and-the-sandbox

By sindresorhus at Jan. 2, 2019, 11:27 a.m. (reply...)

Related Radar

https://openradar.appspot.com/radar?id=4931161214156800

By sindresorhus at Jan. 2, 2019, 11:26 a.m. (reply...)

Twitter thread

https://twitter.com/sindresorhus/status/1080417460359176192

By sindresorhus at Jan. 2, 2019, 11:23 a.m. (reply...)

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!