使用UseMauiEmbedding导致iOS端NavigationController为空的问题
问题背景
将MAUI ContentView嵌入已迁移至.NET7的Xamarin iOS项目时出现以下异常:
- 注释
builder.UseMauiEmbedding代码,项目可正常运行,NavigationController能被正常识别; - 取消注释该代码后,启动屏加载时获取
NavigationController.Parent时,NavigationController返回Null,触发空引用崩溃; - 核心需求是获取MauiContext以打开MAUI ContentView,但添加
builder.UseMauiEmbedding后原有导航结构被破坏。
相关代码片段
AppDelegate代码
public override bool FinishedLaunching(UIApplication app, NSDictionary options) { ... var builder = MauiApp.CreateBuilder(); // 添加该行后NavigationController变为null builder.UseMauiEmbedding<Microsoft.Maui.Controls.Application>(); return true; }
MenuController代码(崩溃触发点)
private HomeController HomeController { get { return (NavigationController.ParentViewController as SlideoutNavigationController).TopView as HomeController; } }
崩溃日志
2023-08-30 15:57:09.129 LIC.MINDAMobile.iOS[15792:11028708] [AppCenterXamarinCrashes] ERROR: +[MSACWrapperLogger MSACWrapperLog:tag:level:]/10 Unhandled Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object. at LIC.MINDAMobile.iOS.MenuController.get_HomeController() in /Users/stall1/Projects/LIC/mobile-minda/LIC.MINDAMobile.iOS/Controllers/MenuController.cs:line 51 at LIC.MINDAMobile.iOS.MenuController.ViewDidLoad() in /Users/stall1/Projects/LIC/mobile-mi
解决方案
1. 延迟导航控制器的获取逻辑
添加builder.UseMauiEmbedding后,MAUI初始化会改变iOS应用的启动流程,导致ViewDidLoad阶段导航控制器还未完成绑定。将依赖NavigationController的逻辑延迟到视图完全显示后执行:
private HomeController _homeController; public override void ViewDidAppear(bool animated) { base.ViewDidAppear(animated); _homeController = (NavigationController.ParentViewController as SlideoutNavigationController).TopView as HomeController; // 所有依赖_homeController的业务逻辑移至此处 }
2. 手动初始化并保留MauiContext
在初始化MAUI嵌入时,手动构建并保存MauiContext,避免干扰原有Xamarin导航结构的初始化:
public override bool FinishedLaunching(UIApplication app, NSDictionary options) { ... var builder = MauiApp.CreateBuilder(); builder.UseMauiEmbedding<Microsoft.Maui.Controls.Application>(); var mauiApp = builder.Build(); // 将MauiContext存储到全局可访问位置(比如App类的静态属性) App.MauiContext = new MauiContext(mauiApp.Services, this); return true; }
3. 调整导航结构与MAUI初始化的顺序
确保Xamarin原有导航结构的初始化在MAUI嵌入代码之前完成,保证导航控制器在MAUI启动前已绑定到窗口:
public override bool FinishedLaunching(UIApplication app, NSDictionary options) { // 先初始化Xamarin导航结构 window = new UIWindow(UIScreen.MainScreen.Bounds); var slideoutNav = new SlideoutNavigationController(); var navController = new UINavigationController(new HomeController()); slideoutNav.TopView = navController; window.RootViewController = slideoutNav; window.MakeKeyAndVisible(); // 再初始化MAUI嵌入 var builder = MauiApp.CreateBuilder(); builder.UseMauiEmbedding<Microsoft.Maui.Controls.Application>(); var mauiApp = builder.Build(); App.MauiContext = new MauiContext(mauiApp.Services, this); return true; }
4. 添加空引用防护逻辑
修改HomeController属性的getter,增加空值检查,避免直接崩溃同时便于调试定位问题:
private HomeController HomeController { get { if (NavigationController == null) { Console.WriteLine("NavigationController未初始化"); return null; } var slideoutNav = NavigationController.ParentViewController as SlideoutNavigationController; if (slideoutNav == null) { Console.WriteLine("父视图控制器不是SlideoutNavigationController类型"); return null; } return slideoutNav.TopView as HomeController; } }
内容的提问来源于stack exchange,提问作者Stuart Allen
相关产品推荐
相关产品推荐

