如何访问用户选定目录下的(只读)文件?

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

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
返回错误)

swift macos swiftui appstore-sandbox
1个回答
0
投票

最近,我找到了受iina/iina源代码启发的解决方案。

  1. 请求访问目录
guard selection.startAccessingSecurityScopedResource() else {
    return
}
viewModel.activeURL = selection

保持对此目录的访问权限,直到不需要为止。对我来说,我确实喜欢这样:

class ViewModel: ObservableObject {
    var activeURL: URL? {
        didSet {
            oldValue?.stopAccessingSecurityScopedResource()
        }
    }
    
    deinit {
        activeURL?.stopAccessingSecurityScopedResource()
    }
}
  1. 使用

    FileManager.default.contentsOfDirectory(atPath: selection.path(percentEncoded: false))
    代替
    FileManager.default.contentsOfDirectory(at:selection,includingPropertiesForKeys: nil)

  2. 生成这样的内容 URL:

let url = selection.appending(path: path, directoryHint: .notDirectory)
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.