如何在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
相关产品推荐
相关产品推荐

