沙盒下的 NSOpenPanel - 访问用户选择文件夹内的所有文件

NSOpenPanel under Sandbox - Access All Files inside User Selected folder

我的 沙盒 macOS 应用程序导入图像文件 select 由用户通过 NSOpenPanel 模式 window 编辑,这是惯例。

起初,我将面板配置为canChooseDirectories = false,并将allowedFileTypes 属性设置为NSImage.imageTypes。到目前为止一切顺利。

使用该应用程序后,我意识到我要导入的图像通常都集中在一个文件夹中,里面什么也没有。如果我能让用户只 select 包含文件夹并在 "wholesale" 中导入图像,那就太好了,所以我采用了这个代码:

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...)

...但是 try 语句 总是失败 ,执行 catch 块并抛出错误是:

"The file “MyImageFolder” couldn’t be opened because you don’t have permission to view it."

沙盒应用程序是否有解决此问题的方法?我忘记了什么,这将使我能够 阅读用户 select 编辑的文件夹的内容?


附录: Apple's documentation 指出:

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.

(强调我的)

我有点过早地接受了 @vadian's quick answer,但似乎我 可以 NSOpenPanel 访问用户选择的文件夹中的各个文件。

阅读 this answer 之后(我一开始在搜索时不知何故错过了),我发现下面的代码有效:

// Warning! This code does not deal with the user selecting 
// multiple folders!

let urls: [URL] = {

    if inputURLs.count == 1, inputURLs[0].hasDirectoryPath {
        // Folder; Read its contents:
        do {
            let urls = try FileManager.default.contentsOfDirectory(at: inputURLs[0], includingPropertiesForKeys: nil, options: [])
                return urls

        } catch {
            // (todo: Handle Errors)
            return []
        }
    } else {
        // One or more images; Read them directly:
        return inputURLs
    }
}()

我似乎犯的另一个错误是使用 NSURLisFileURL 属性 来区分所选文件夹和单个文件:it returns true 也适用于文件夹!

所以在我从使用 panel.directoryURL 切换到使用 panel.urls[0] 之后(当 isFileURLtrue 时),我的应用程序试图从目录中读取单个图像URL。没有违反沙箱,但也没有读取图像。

根据文档,属性 returns true "if the receiver uses the file scheme"(不管是什么意思)。我猜文件夹也是 "use the file scheme"。 我改为使用 hasDirectoryPath,如 this other answer.

中所建议