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

如何在Flutter插件代码中使用UIKit ViewController?遇UIDocumentPicker问题

解决Flutter插件中UIDocumentPickerViewController的报错问题

遇到的错误

flutter_download_manager_darwin/ios/Classes/SwiftFlutterDownloadManagerDarwinPlugin.swift:16:15: No exact matches in call to initializer 
flutter_download_manager_darwin/ios/Classes/SwiftFlutterDownloadManagerDarwinPlugin.swift:16:15: Found candidate with type '([URL]) -> UIDocumentPickerViewController'
flutter_download_manager_darwin/ios/Classes/SwiftFlutterDownloadManagerDarwinPlugin.swift:16:15: Found candidate with type '([URL]) -> UIDocumentPickerViewController'
flutter_download_manager_darwin/ios/Classes/SwiftFlutterDownloadManagerDarwinPlugin.swift:16:72: Type 'Array<URL>.ArrayLiteralElement' (aka 'URL') has no member 'folder'
flutter_download_manager_darwin/ios/Classes/SwiftFlutterDownloadManagerDarwinPlugin.swift:21:41: Cannot find 'startingDirectory' in scope
flutter_download_manager_darwin/ios/Classes/SwiftFlutterDownloadManagerDarwinPlugin.swift:25:11: Cannot find 'present' in scope

错误原因及修复方案

1. 初始化方法错误 + .folder 未识别

  • 原因:.folder 属于 UTType 类型,需导入对应框架才能使用,且初始化选择器时的参数类型不匹配。
  • 修复:
    • 顶部添加导入语句:import UniformTypeIdentifiers
    • 修改初始化代码为:
      let documentPicker = UIDocumentPickerViewController(forOpeningContentTypes: [UTType.folder])
      

2. startingDirectory 未定义

  • 原因:代码中直接使用了未声明的变量,需先定义初始目录的URL。
  • 修复:根据需求指定初始目录,比如使用系统文档目录:
    guard let startingDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
        result(FlutterError(code: "DIRECTORY_ERROR", message: "无法获取初始目录", details: nil))
        return
    }
    

3. present 方法找不到

  • 原因:Flutter插件类不是UIViewController,无法直接调用present,需通过根视图控制器弹出选择器。
  • 修复:获取当前应用的根VC来present:
    if let rootVC = UIApplication.shared.windows.first?.rootViewController {
        rootVC.present(documentPicker, animated: true, completion: nil)
    } else {
        result(FlutterError(code: "VC_ERROR", message: "无法获取根视图控制器", details: nil))
        return
    }
    

4. 未实现UIDocumentPickerDelegate协议

  • 原因:设置了documentPicker.delegate = self,但类未遵守该协议,会导致编译错误,同时需要实现回调将结果返回给Flutter。
  • 修复:添加协议扩展并实现回调,同时在类中保存Flutter回调对象:
    // 类内添加属性保存回调
    private var result: FlutterResult?
    
    // 扩展实现协议
    extension SwiftFlutterDownloadManagerDarwinPlugin: UIDocumentPickerDelegate {
        public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
            guard let selectedUrl = urls.first else { return }
            result?(selectedUrl.absoluteString)
            result = nil
        }
    
        public func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
            result?(nil)
            result = nil
        }
    }
    

完整修正后的代码

import Flutter
import UIKit
import UniformTypeIdentifiers

public class SwiftFlutterDownloadManagerDarwinPlugin: NSObject, FlutterPlugin {
    private var result: FlutterResult?
    
    public static func register(with registrar: FlutterPluginRegistrar) {
        let channel = FlutterMethodChannel(name: "flutter_download_manager_darwin", binaryMessenger: registrar.messenger())
        let instance = SwiftFlutterDownloadManagerDarwinPlugin()
        registrar.addMethodCallDelegate(instance, channel: channel)
    }

    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        switch call.method {
        case "pickDirectoryUrl":
            self.result = result
            
            // 创建目录选择器
            let documentPicker = UIDocumentPickerViewController(forOpeningContentTypes: [UTType.folder])
            documentPicker.delegate = self
            documentPicker.allowsMultipleSelection = false
            
            // 设置初始目录
            guard let startingDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
                result(FlutterError(code: "DIRECTORY_ERROR", message: "无法获取初始目录", details: nil))
                self.result = nil
                return
            }
            documentPicker.directoryURL = startingDirectory
            
            // 弹出选择器
            if let rootVC = UIApplication.shared.windows.first?.rootViewController {
                rootVC.present(documentPicker, animated: true, completion: nil)
            } else {
                result(FlutterError(code: "VC_ERROR", message: "无法获取根视图控制器", details: nil))
                self.result = nil
            }
        default:
            result(FlutterMethodNotImplemented)
        }
    }
}

extension SwiftFlutterDownloadManagerDarwinPlugin: UIDocumentPickerDelegate {
    public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
        guard let selectedUrl = urls.first else {
            result?(nil)
            result = nil
            return
        }
        result?(selectedUrl.absoluteString)
        result = nil
    }

    public func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
        result?(nil)
        result = nil
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 21:39:20