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

如何在Flutter iOS Swift插件中获取UINavigationController

iOS Flutter插件中获取UINavigationController的解决方案

你之前的代码失败,核心原因是Flutter默认的根视图控制器是FlutterViewController,而非直接的UINavigationController,直接强转自然会失败。以下是几种可靠的实现方式:

方法一:通过插件Registrar获取关联的ViewController(推荐)

Flutter插件注册时的FlutterPluginRegistrar可以直接拿到当前插件绑定的FlutterViewController,再从这个VC向上查找导航控制器,这是最稳定的方式。

完整代码示例

import Flutter
import UIKit

public class SwiftYourPluginPlugin: NSObject, FlutterPlugin {
    private var registrar: FlutterPluginRegistrar?
    
    public static func register(with registrar: FlutterPluginRegistrar) {
        let channel = FlutterMethodChannel(name: "your_plugin_channel", binaryMessenger: registrar.messenger())
        let instance = SwiftYourPluginPlugin()
        instance.registrar = registrar // 保存Registrar引用
        registrar.addMethodCallDelegate(instance, channel: channel)
    }
    
    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        // 第一步:获取当前绑定的FlutterViewController
        guard let flutterVC = registrar?.viewController() else {
            result(FlutterError(code: "-2", message: "无法获取Flutter视图控制器", details: nil))
            return
        }
        
        // 第二步:优先获取当前VC的导航控制器
        if let navController = flutterVC.navigationController {
            // 在这里使用navController调用第三方框架
            result(nil)
            return
        }
        
        // 第三步:遍历父视图层级查找导航控制器
        var currentVC = flutterVC
        while let parentVC = currentVC.parent {
            currentVC = parentVC
            if let navController = currentVC as? UINavigationController {
                // 使用找到的导航控制器
                result(nil)
                return
            }
        }
        
        // 第四步:兜底检查窗口层级的导航控制器(适配iOS 13+多场景)
        if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
           let keyWindow = windowScene.windows.first(where: { $0.isKeyWindow }),
           let rootVC = keyWindow.rootViewController {
            
            if let navController = rootVC as? UINavigationController {
                result(nil)
            } else if let navController = rootVC.presentedViewController as? UINavigationController {
                result(nil)
            } else {
                result(FlutterError(code: "-1", message: "未找到可用的UINavigationController", details: nil))
            }
        } else {
            result(FlutterError(code: "-3", message: "无法获取当前活跃窗口", details: nil))
        }
    }
}

关键说明

  1. 避免直接强转rootViewController:Flutter项目默认不会把FlutterViewController包裹在UINavigationController中,除非你手动在iOS工程的AppDelegate/SceneDelegate里做了配置。
  2. iOS 13+适配:不要再用UIApplication.shared.windows.first获取窗口,改用connectedScenes获取当前活跃的窗口场景,避免多场景下的异常。
  3. 层级遍历的必要性:如果你的Flutter页面是被其他原生VC present出来的,直接取navigationController可能为空,此时需要向上遍历父VC层级查找导航栈。

内容的提问来源于stack exchange,提问作者KT AT CBX

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 00:15:12