Mac Catalyst下UIDocumentPickerViewController沙箱配置与回调异常问题
问题解决方案
错误根源
你遇到的didPickDocumentsAt不触发问题,是沙箱权限不匹配导致:当前你配置的是用户选中文件只读权限,但系统默认尝试为选中文件申请读写沙箱扩展,权限申请被拒绝后回调直接中断,只有取消操作不受权限影响可以正常触发。
修复步骤
调整沙箱权限配置
打开项目Signing & Capabilities中的App Sandbox配置,将「User Selected File」的权限从「Read Only」改为Read/Write,匹配系统默认的扩展申请要求。修正
AudioFilePicker实现错误
不要将UIDocumentPickerViewController作为存储属性提前初始化,SwiftUI视图刷新时会导致实例上下文异常,正确实现需要将初始化逻辑移到makeUIViewController方法内:final class AudioFilePicker: UIViewControllerRepresentable { class Coordinator: NSObject, UIDocumentPickerDelegate { var parent: AudioFilePicker init(parent: AudioFilePicker) { self.parent = parent } func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { guard let url = urls.first else { return } // Mac Catalyst下必须开启安全域访问才能读取文件 let hasAccess = url.startAccessingSecurityScopedResource() defer { if hasAccess { url.stopAccessingSecurityScopedResource() } } print("Picker Loaded: \(url.absoluteString)") // 后续文件处理逻辑 } func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) { print("Picker Cancelled") } } func makeCoordinator() -> Coordinator { return Coordinator(parent: self) } func makeUIViewController(context: Context) -> UIDocumentPickerViewController { // 跨平台适配asCopy参数 #if targetEnvironment(macCatalyst) let asCopy = false #else let asCopy = true #endif let picker = UIDocumentPickerViewController(forOpeningContentTypes: [.item], asCopy: asCopy) picker.delegate = context.coordinator return picker } func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) { } }可选只读权限适配
如果你确实只需要读取文件不需要写入权限,不需要修改沙箱权限,只需要在初始化picker后添加以下配置,告知系统仅申请读权限:picker.allowsWriting = false
其他注意事项
- 每次修改沙箱权限后需要清理Xcode构建缓存(Shift+Command+K)再运行,避免旧配置缓存导致验证失败
- 所有通过文档选择器拿到的URL,都必须调用
startAccessingSecurityScopedResource()开启安全域访问,使用完成后调用停止方法,否则会出现无权限读取文件的问题
内容的提问来源于stack exchange,提问作者NSGoat
相关产品推荐
相关产品推荐

