SDK:MacOS 14.0

Xcode:15.0

我搜索了很多答案,但都不适用于我的申请.我无法访问文件夹下的文件内容.

首先,我在App SandBox中配置了权限:

enter image description here

然后我在SwiftUI中使用fileImporter来允许用户 Select 文件夹:

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的源代码的启发下找到了解决方案.

  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)

Swift相关问答推荐

{Singleton类}类型的值没有成员$showegView'

格式化单位和度量值.为什么从符号初始化的单位不能产生与静态初始化相同的结果

Swift-Can无法在AudioKit中找出简单的麦克风效果-文件链

如何使用变量 Select 哪个向量(?)在我的 struct 中密谋吗?

如何在SwiftUI 4+(iOS 16+)中使用新的NavigationStack进行导航

在表单中对齐文本框

设备上ScrollView为什么会将内容高度更改为随机值,而在预览上不会? - 优化后的标题:设备上ScrollView内容高度随机变化问题解决

从 Obj-C 函数返回 swift 类的不兼容指针类型

如何使用 Swift 在非本地函数中切换()一个 Bool?

使用异步收集发布者值

在 SwiftUI 中禁用 Select 器选项

如何从 RC 加载场景作为 ModelEntity 而不是普通实体?

Swiftui 无法从核心数据中获取数据

关于变量的视图的 SwiftUI 生命周期

类型 '()' 不能符合 View (除非它肯定是 View,这次没有恶作剧)

为什么更改属性后动画会加速? SwiftUI

如何有条件地格式化 SwiftUI 代码

单元测试和私有变量

不支持用作符合协议 AnyObject 的具体类型

UITableViewAlertForLayoutOutsideViewHierarchy 错误:仅警告一次(iOS 13 GM)