Sandbox下的NSOpenPanel - 访问User Selected文件夹中的所有文件

问题描述 投票:2回答:1

我的沙盒macOS应用程序通常按照惯例导入用户通过NSOpenPanel模式窗口选择的图像文件。

首先,我将面板配置为canChooseDirectories = false,并将allowedFileTypes属性设置为NSImage.imageTypes。到现在为止还挺好。

使用该应用程序,我意识到我想要导入的图像往往都是在一个文件夹中分组而已。如果我可以让用户只选择包含文件夹并在“批发”中导入图像,那将是很好的,所以我采用了这个代码:

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块并抛出错误:

“无法打开文件”MyImageFolder“,因为您无权查看它。”

对于沙盒应用程序,有没有办法解决这个问题?我忘记了什么,这将允许我阅读用户选择的文件夹的内容?


附录:Apple's documentation声明:

当应用程序的用户指定他们要使用文件或文件夹时,系统会将相关路径添加到应用程序的沙箱中。比如说,例如,用户将〜/ Documents文件夹拖到应用程序的Dock磁贴上(或者移动到应用程序的Finder图标上,或拖到应用程序的打开窗口中),从而表明他们想要使用该文件夹。作为响应,系统使〜/ Documents文件夹,其内容及其子文件夹可供您的应用程序使用。

(强调我的)

macos cocoa sandbox nsopenpanel
1个回答
0
投票

我过早地接受了@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属性来区分所选的文件夹和单个文件:它也会为文件夹返回true

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

根据文档,该属性返回true“如果接收者使用文件方案”(无论这意味着什么)。我猜文件夹也“使用文件方案”。我转而使用hasDirectoryPath,正如this other answer所建议的那样。

© www.soinside.com 2019 - 2024. All rights reserved.