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

使用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) { }
}

关键修改说明

  1. 安全权限修正:

    • 先对选中的父文件夹申请安全访问权限,处理权限获取失败的情况。
    • 枚举子项时,对每个fileURL单独申请安全权限,适配网络驱动器的权限验证规则。
  2. 移除冗余操作:删除resolvingSymlinksInPath()调用,保留原始URL的安全标识。

  3. 增强错误处理:

    • 不再强制解包文件枚举器,添加创建失败的判断逻辑。
    • 捕获NSFileCoordinator和文件属性获取过程中的异常,便于排查网络访问问题。
    • 新增skipsHiddenFiles枚举选项,减少不必要的枚举项。

内容的提问来源于stack exchange,提问作者andrewcfitz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 14:15:44