我的沙盒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文件夹,其内容及其子文件夹可供您的应用程序使用。
(强调我的)
我过早地接受了@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
}
}()
我似乎要犯的另一个错误是使用NSURL
的isFileURL
属性来区分所选的文件夹和单个文件:它也会为文件夹返回true
!
所以在我从使用panel.directoryURL
切换到使用panel.urls[0]
(当isFileURL
是true
)时,我的应用程序试图从目录URL中读取单个图像。没有沙箱违规,但也没有图像读取。
根据文档,该属性返回true
“如果接收者使用文件方案”(无论这意味着什么)。我猜文件夹也“使用文件方案”。我转而使用hasDirectoryPath
,正如this other answer所建议的那样。