SDK:macOS 14.0
Xcode:15.0
我搜索了很多答案,但对我的应用程序不起作用。我无法访问该文件夹下的文件内容。
首先,我在App SandBox中配置了权限:
然后我在 SwiftUI 中使用
fileImporter
来允许用户选择文件夹:
Button("open file")
.fileImporter(
isPresented: $indexModel.openFileImporter,
allowedContentTypes: [.movie, .avi, .mpeg4Movie, .directory],
allowsMultipleSelection: true
) { results in
do {
let selection = try results.get()
try self.openSelectedPath(selection)
} catch let err {
indexModel.errorMsg = err.localizedDescription
indexModel.showError = true
}
}
在
openSelectedPath
中,我通过FileManager
访问文件夹下的内容:
if selection.hasDirectoryPath {
let files = try FileManager.default.contentsOfDirectory(
at: selection,
includingPropertiesForKeys: nil,
options: [.skipsHiddenFiles]
)
files.enumerated().filter { _, file in
// try grant access here but all fails
guard file.startAccessingSecurityScopedResource() else {
print("\(file.lastPathComponent) cannot access")
return false
}
let isMKV = file.pathExtension.compare("mkv", options: .caseInsensitive, range: nil, locale: nil) == .orderedSame
return file.isFileURL && (isMKV || file.contains(.movie) || file.contains(.avi) || file.contains(.mpeg4Movie))
}
return
}
因此,该文件夹中的所有文件都无法访问。 (
file.startAccessingSecurityScopedResource
返回错误)
最近,我找到了受iina/iina源代码启发的解决方案。
guard selection.startAccessingSecurityScopedResource() else {
return
}
viewModel.activeURL = selection
保持对此目录的访问权限,直到不需要为止。对我来说,我确实喜欢这样:
class ViewModel: ObservableObject {
var activeURL: URL? {
didSet {
oldValue?.stopAccessingSecurityScopedResource()
}
}
deinit {
activeURL?.stopAccessingSecurityScopedResource()
}
}
使用
FileManager.default.contentsOfDirectory(atPath: selection.path(percentEncoded: false))
代替 FileManager.default.contentsOfDirectory(at:selection,includingPropertiesForKeys: nil)
生成这样的内容 URL:
let url = selection.appending(path: path, directoryHint: .notDirectory)