You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS16及以上版本UIDocumentPickerViewController文件夹选择问题

解决iOS16+ SwiftUI中UIDocumentPickerViewController文件夹选择问题

问题原因

  1. 同时指定UTType.folder和文件类型(如UTType.text)时,iOS16+的文档选择器会默认以文件选择模式启动,导致文件夹的选择按钮不显示。
  2. 使用了已废弃的allowsMultipleSelection属性,iOS14+应改用allowsPickingMultipleItems。
  3. 未正确处理沙盒安全访问权限,可能导致后续无法正常访问选中的文件夹。

解决方案

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 21:46:05