使用UIDocumentPickerViewController导入网络驱动器文件夹遇问题
iOS 网络驱动器文件夹枚举失败的问题修复
你的代码存在几个关键问题,导致网络驱动器下的文件无法正常枚举,以下是问题分析和修复方案:
核心问题点
- 安全作用域资源调用错误:循环中反复对父文件夹URL调用安全权限申请,而网络驱动器的每个子文件/文件夹都需要单独申请安全访问权限。
- 不必要的符号链接解析:
resolvingSymlinksInPath()会破坏网络驱动器URL的安全作用域标识,导致权限验证失效。 - 强制解包风险:直接强制解包文件枚举器,忽略了网络环境下枚举失败的可能性。
- 错误处理缺失:未捕获文件协调和属性获取过程中的异常,无法定位网络访问失败的具体原因。
修复后的完整代码
import SwiftUI import UniformTypeIdentifiers @main struct OpenNetworkFileApp: App { var body: some Scene { WindowGroup { ContentView() } } } struct ContentView: View { @State private var documentPickerIsPresented = false var body: some View { Button("Click Me") { documentPickerIsPresented = true } .sheet(isPresented: $documentPickerIsPresented) { DocumentPicker() } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } public struct DocumentPicker: UIViewControllerRepresentable { public func makeCoordinator() -> DocumentPickerCoordinator { DocumentPickerCoordinator() } public func makeUIViewController(context: Context) -> UIDocumentPickerViewController { let controller = UIDocumentPickerViewController(forOpeningContentTypes: [.folder], asCopy: false) controller.delegate = context.coordinator return controller } public func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) { } } public class DocumentPickerCoordinator: NSObject, UIDocumentPickerDelegate, UINavigationControllerDelegate { public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) { // 申请父文件夹的安全访问权限 guard url.startAccessingSecurityScopedResource() else { print("无法访问父文件夹安全资源") return } defer { url.stopAccessingSecurityScopedResource() } var coordinatedError: NSError? NSFileCoordinator().coordinate(readingItemAt: url, error: &coordinatedError) { folderURL in let keys: [URLResourceKey] = [.nameKey, .isDirectoryKey] // 处理枚举器创建失败的情况 guard let fileEnumerator = FileManager.default.enumerator(at: folderURL, includingPropertiesForKeys: keys, options: [.skipsHiddenFiles]) else { print("无法创建文件枚举器") return } for case let fileURL as URL in fileEnumerator { // 对每个子文件/文件夹单独申请安全访问权限 guard fileURL.startAccessingSecurityScopedResource() else { print("无法访问文件安全资源: \(fileURL.lastPathComponent)") continue } defer { fileURL.stopAccessingSecurityScopedResource() } // 获取并打印文件属性 do { let attributes = try fileURL.resourceValues(forKeys: keys) print("\(attributes.name ?? "未知名称") - 是文件夹: \(attributes.isDirectory ?? false)") } catch { print("获取文件属性失败: \(error.localizedDescription)") } } } // 捕获文件协调过程中的错误 if let error = coordinatedError { print("文件协调错误: \(error.localizedDescription)") } } public func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) { } }
关键修改说明
安全权限修正:
- 先对选中的父文件夹申请安全访问权限,处理权限获取失败的情况。
- 枚举子项时,对每个
fileURL单独申请安全权限,适配网络驱动器的权限验证规则。
移除冗余操作:删除
resolvingSymlinksInPath()调用,保留原始URL的安全标识。增强错误处理:
- 不再强制解包文件枚举器,添加创建失败的判断逻辑。
- 捕获
NSFileCoordinator和文件属性获取过程中的异常,便于排查网络访问问题。 - 新增
skipsHiddenFiles枚举选项,减少不必要的枚举项。
内容的提问来源于stack exchange,提问作者andrewcfitz
相关产品推荐
相关产品推荐

