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

升级MvvmCross 7.0.0后Xamarin iOS应用无法启动首页面

Xamarin iOS升级MvvmCross 7.0后启动页卡死,ViewDidLoad未执行

将Xamarin iOS应用的MvvmCross升级至7.0.0版本后,应用卡在启动页,无法正常加载首个视图控制器。排查后发现:

  • AppDelegate和Setup文件无明显异常
  • 视图控制器构造函数及ViewModel均被触发,但ViewDidLoad方法完全未执行
  • 调整代码后偶尔出现ViewModel未绑定到视图(DataContext为空)或set.Apply()报错的情况
  • 即便无报错,LoginView始终无法显示,应用持续停留在启动页

相关代码

AppDelegate代码

[Register("AppDelegate")]
[assembly: Preserve(typeof(MvxIosSetup<App>))]
public partial class AppDelegate : MvxApplicationDelegate<MvxIosSetup<App>, App>
{
    /// <summary>
    /// UIApplicationDelegate.Window doesn't really exist / work. It was added by Xamarin.iOS templates 
    /// </summary>
    public new virtual UIWindow Window { get; set; }

    public AppDelegate() : base()
    {
        RegisterSetup();
    }

    public override void WillEnterForeground(UIApplication application)
    {
        FireLifetimeChanged(MvxLifetimeEvent.ActivatedFromMemory);
    }

    public override void DidEnterBackground(UIApplication application)
    {
        FireLifetimeChanged(MvxLifetimeEvent.Deactivated);
    }

    public override void WillTerminate(UIApplication application)
    {
        FireLifetimeChanged(MvxLifetimeEvent.Closing);
    }

    public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
    {
        Window = new UIWindow(UIScreen.MainScreen.Bounds);

        var setup = new Setup();
        setup.InitializePrimary();
        setup.InitializeSecondary();
        setup.PlatformInitialize(this, Window);

        var myFirstViewController = new LoginView();
        Window.RootViewController = myFirstViewController;

        var startup = Mvx.IoCProvider.Resolve<IMvxAppStart>();
        startup.Start();

        Window.MakeKeyAndVisible();


        SetupUiStyles();

        return true;
    }

    private void FireLifetimeChanged(MvxLifetimeEvent which)
    {
        var handler = LifetimeChanged;
        handler?.Invoke(this, new MvxLifetimeEventArgs(which));
    }

    public event EventHandler<MvxLifetimeEventArgs> LifetimeChanged;

    private void SetupUiStyles()
    {
        UINavigationBar.Appearance.TintColor = UIColor.Black;
        UIApplication.SharedApplication.StatusBarStyle = UIStatusBarStyle.Default;

        if (UIDevice.CurrentDevice.CheckSystemVersion(15, 0))
        {
            var appearance = new UINavigationBarAppearance()
            {
                BackgroundColor = UIColor.FromRGB(99, 183, 105),
                TitleTextAttributes = new UIStringAttributes() { ForegroundColor = UIColor.White }
            };


            UINavigationBar.Appearance.StandardAppearance = appearance;
            UINavigationBar.Appearance.CompactAppearance = appearance;
            UINavigationBar.Appearance.ScrollEdgeAppearance = appearance;
        }

        UIApplication.CheckForEventAndDelegateMismatches = false;
    }
   
}

Setup类代码

public class Setup : MvxIosSetup<App>
{
    public Setup()
    {

    }

    protected override IMvxApplication CreateApp()
    {
        return new App();
    }

    protected override IMvxIosViewPresenter CreateViewPresenter()
    {
        return new MvxIosViewPresenter(ApplicationDelegate, Window);
    }

    protected override void InitializeFirstChance()
    {           
        base.InitializeFirstChance();
    }

    public override void InitializeSecondary()
    {
        Mvx.IoCProvider.RegisterType<LoginViewModel, LoginViewModel>();
        InitializeViewModelTypeFinder();
        base.InitializeSecondary();
    }


    protected override IMvxNameMapping InitializeViewModelTypeFinder()
    {
        var viewModelByNameRegistry = CreateViewModelByNameRegistry();

        var viewModelAssemblies = GetViewModelAssemblies();

        foreach(var assemly in viewModelAssemblies)
        {
            viewModelByNameRegistry.AddAll(assemly);
        }

        var nameMapping = CreateViewToViewModelNaming();
        Mvx.IoCProvider.RegisterSingleton(nameMapping);

        return nameMapping;
    }

}

BaseView基类代码

public class BaseView<T> : MvxViewController where T : MvxViewModel
{
    protected BaseView(string name, NSBundle bundle = null)
    {

    }

    public new T ViewModel
    {
        get
        {
            return base.ViewModel as T;
        }
        set
        {
            base.ViewModel = value;
        }

    }

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
    }
}

LoginView代码

[MvxRootPresentation]
public partial class LoginView : BaseView<LoginViewModel>, IBaseView
{
    public LoginView()
        : base("LoginView", null)
    {
       // being hit
    }

   public override void ViewDidLoad()
    {
        base.ViewDidLoad();
        //not being hit
    }
}

问题根源与修复方案

1. 修复AppDelegate启动流程

MvvmCross 7.0已自动处理Setup初始化,手动实例化Setup并调用初始化会导致重复初始化,破坏视图展示逻辑。修改FinishedLaunching方法:

public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
    Window = new UIWindow(UIScreen.MainScreen.Bounds);

    // 移除手动初始化Setup的代码,交由Mvx框架自动处理
    var result = base.FinishedLaunching(application, launchOptions);

    // 无需手动创建LoginView,交由IMvxAppStart导航到根视图
    Window.MakeKeyAndVisible();

    SetupUiStyles();

    return result;
}

同时移除AppDelegate构造函数中冗余的RegisterSetup()调用:

public AppDelegate() : base()
{
    // 移除RegisterSetup();
}

2. 简化Setup类

MvvmCross 7.0自动处理ViewModel注册和视图映射,无需手动重写InitializeSecondary和InitializeViewModelTypeFinder,简化后的Setup类:

public class Setup : MvxIosSetup<App>
{
    protected override IMvxApplication CreateApp()
    {
        return new App();
    }

    protected override IMvxIosViewPresenter CreateViewPresenter()
    {
        return new MvxIosViewPresenter(ApplicationDelegate, Window);
    }
}

3. 配置App启动导航

确保App类中正确配置IMvxAppStart,指定启动时导航到LoginViewModel:

public class App : MvxApplication
{
    public override void Initialize()
    {
        RegisterCustomAppStart<LoginViewModel>();
    }
}

4. 修复BaseView构造函数

MvxViewController需要正确初始化视图,修改BaseView确保调用基类正确构造方法:

public class BaseView<T> : MvxViewController<T> where T : MvxViewModel
{
    protected BaseView(string nibName, NSBundle bundle) : base(nibName, bundle)
    {
    }

    // 支持Storyboard加载的构造函数
    protected BaseView(IntPtr handle) : base(handle)
    {
    }

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
    }
}

对应的LoginView更新构造函数:

[MvxRootPresentation]
public partial class LoginView : BaseView<LoginViewModel>, IBaseView
{
    public LoginView() : base("LoginView", null)
    {
    }

    public LoginView(IntPtr handle) : base(handle)
    {
    }

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
        // 现在会被执行
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 17:10:21