My sandboxed macOS app imports image files selected by the user via an NSOpenPanel
modal window, as is customary.
At first, I configured the panel to canChooseDirectories = false
, and set the allowedFileTypes
property to NSImage.imageTypes
. So far so good.
Using the app, I realized that the images I want to import are more often than not all grouped inside a folder with nothing more in it. It would be great if I could have the user just select the containing folder and import the images within "wholesale", so I adopted this code:
let panel = NSOpenPanel()
panel.allowsMultipleSelection = true
panel.canChooseDirectories = true
panel.canCreateDirectories = false
panel.canChooseFiles = true
panel.allowedFileTypes = NSImage.imageTypes
panel.begin { [unowned self] (result) in
guard result == .OK else {
return // User cancelled
}
// Read all selected images:
let urls: [URL] = {
if let directory = panel.directoryURL {
// .........................................
// [A] One directory selected:
do {
let urls = try FileManager.default.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil, options: [])
return urls
} catch {
// (I ALWAYS END UP HERE)
print(error.localizedDescription)
return []
}
} else {
// .........................................
// [B] One or more files selected:
return panel.urls
}
}()
// (next: read individual urls...)
...but the try
statement always fails, the catch
block is executed and the error thrown is:
"The file “MyImageFolder” couldn’t be opened because you don’t have permission to view it."
Is there a way around this for sandboxed apps? Anything that I am forgetting, that will allow me to read the contents of a user-selected folder?
Addendum: Apple's documentation states that:
When a user of your app specifies they want to use a file or a folder, the system adds the associated path to your app’s sandbox. Say, for example, a user drags the ~/Documents folder onto your app’s Dock tile (or onto your app’s Finder icon, or into an open window of your app), thereby indicating they want to use that folder. In response, the system makes the ~/Documents folder, its contents, and its subfolders available to your app.
(emphasis mine)