iOS16及以上版本UIDocumentPickerViewController文件夹选择问题
解决iOS16+ SwiftUI中UIDocumentPickerViewController文件夹选择问题
问题原因
- 同时指定
UTType.folder和文件类型(如UTType.text)时,iOS16+的文档选择器会默认以文件选择模式启动,导致文件夹的选择按钮不显示。 - 使用了已废弃的
allowsMultipleSelection属性,iOS14+应改用allowsPickingMultipleItems。 - 未正确处理沙盒安全访问权限,可能导致后续无法正常访问选中的文件夹。
解决方案
1. 配置Info.plist权限
在项目的Info.plist中添加文档选择器使用描述,否则选择器可能无法正常启动:
<key>NSDocumentPickerUsageDescription</key> <string>需要访问文件夹以读取/存储内容</string>
2. 修改FolderPicker实现
调整初始化方法专注于文件夹选择,替换废弃属性,并处理安全访问权限:
import SwiftUI import UniformTypeIdentifiers struct FolderPicker: UIViewControllerRepresentable { @Binding var folderURL: String? func makeCoordinator() -> Coordinator { Coordinator(parent: self) } func makeUIViewController(context: Context) -> UIDocumentPickerViewController { // 仅指定文件夹类型,确保选择器进入文件夹选择模式 let picker = UIDocumentPickerViewController(forOpeningContentTypes: [UTType.folder]) picker.delegate = context.coordinator // iOS14+ 替换废弃的allowsMultipleSelection属性 picker.allowsPickingMultipleItems = false // 文件夹选择时建议关闭文件扩展名显示 picker.shouldShowFileExtensions = false return picker } func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) {} class Coordinator: NSObject, UIDocumentPickerDelegate { var parent: FolderPicker init(parent: FolderPicker) { self.parent = parent } func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { guard let folderURL = urls.first else { return } // 申请沙盒临时访问权限 guard folderURL.startAccessingSecurityScopedResource() else { print("无法获取文件夹访问权限") return } defer { // 结束访问,避免资源泄漏 folderURL.stopAccessingSecurityScopedResource() } // 优先存储bookmark数据(持久化访问权限,避免URL失效) do { let bookmark = try folderURL.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil) parent.folderURL = bookmark.base64EncodedString() } catch { print("保存书签失败:\(error.localizedDescription)") parent.folderURL = folderURL.absoluteString } } func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) { parent.folderURL = nil } } }
3. 额外注意事项
- 如果需要同时支持文件和文件夹选择,iOS16+建议使用两个独立的选择器分开处理,避免选择器模式冲突。
- 存储文件夹访问权限时,优先使用bookmark数据而非绝对字符串,沙盒内的文件URL可能会随App重启变化,bookmark可以保证持久化访问。
内容的提问来源于stack exchange,提问作者nekonekopun
相关产品推荐
相关产品推荐

