MvvmCross选项卡控制器包装到UINavigation控制器?

时间:2017-07-27 08:13:59

标签: ios xamarin.ios uinavigationcontroller mvvmcross

我正在使用Xamarin.iOS和MvvmCross 5.x.我的根视图是Tabs Controller,我希望任何显示孩子的请求都会强制在标签之外(而不是在里面)进行堆栈导航。

所以我将我的根视图定义如下:

[MvxFromStoryboard]
[MvxRootPresentation(WrapInNavigationController = true)]
public partial class HomeView : MvxTabBarViewController<HomeViewModel>

不幸的是,根导航控制器不是UINavigationController(正如我所期望的那样基于属性),而是HomeView基本上是标签视图而我无法实现我的目标。

然后我覆盖ios presenter以手动创建根UINavigationController:

public class MySuperCoolIosViewPresenter : MvxIosViewPresenter
{
    private UINavigationController _rootViewController; 

    public MySuperCoolIosViewPresenter(IMvxApplicationDelegate applicationDelegate, UIWindow window)
        : base(applicationDelegate, window)
    {
    }

    protected override void SetWindowRootViewController(UIViewController controller)
    {
        _rootViewController = new UINavigationController(controller);
        base.SetWindowRootViewController(_rootViewController);
    }

    protected override void ShowChildViewController(UIViewController viewController, MvvmCross.iOS.Views.Presenters.Attributes.MvxChildPresentationAttribute attribute, MvxViewModelRequest request)
    {
        _rootViewController.ShowViewController(viewController, _rootViewController);
    }
}

但是在尝试使用以下错误设置控制器base.SetWindowRootViewController(_rootViewController)时,此代码在MvvmCross深处某处失败:

System.NullReferenceException: Object reference not set to an instance of an object\n  
at MvvmCross.iOS.Views.Presenters.MvxIosViewPresenter.CloseTabBarViewController () [0x00036] in <861dee92d7924acc93d876339b4b95f9>:0  
at MvvmCross.iOS.Views.MvxTabBarViewController.ViewWillDisappear (System.Boolean animated) [0x0001f] in <861dee92d7924acc93d876339b4b95f9>:0 
at (wrapper managed-to-native) ObjCRuntime.Messaging:void_objc_msgSend_IntPtr (intptr,intptr,intptr)  
at UIKit.UIWindow.set_RootViewController (UIKit.UIViewController value)

如何在不为根视图创建额外的ViewModel和View的情况下实现我的目标(我不喜欢这种方法,因为在这种情况下Android会吓坏)

2 个答案:

答案 0 :(得分:3)

我创建了这个包含您所需内容的示例:https://github.com/rrispoli/SampleTabs

答案 1 :(得分:0)

当我在寻找解决方案时,来自MvvmCross的人更新了框架以准确解决版本5.1.1的问题(我使用的是5.1.0)。 Ios presenter逻辑已更新,正确地尊重WrapInNavigationController(在标签被忽略之前)。不幸的是ShowChildViewControllerInvalidCastException之后失败了,但我能够通过优先选择我的根导航控制器而不是Tabs控制器来处理这个问题

    protected override void ShowChildViewController(UIViewController viewController, MvxChildPresentationAttribute attribute, MvxViewModelRequest request)
    {
        if (viewController is IMvxSplitViewController)
            throw new MvxException("A SplitViewController cannot be presented as a child. Consider using Root instead");

        if (ModalViewControllers.Any())
        {
            if (ModalViewControllers.LastOrDefault() is UINavigationController modalNavController)
            {
                PushViewControllerIntoStack(modalNavController, viewController, attribute.Animated);
                return;
            }

            throw new MvxException($"Trying to show View type: {viewController.GetType().Name} as child, but there is currently a plain modal view presented!");
        }

        // this logic goes first for the root controller 
        if (MasterNavigationController != null)
        {
            PushViewControllerIntoStack(MasterNavigationController, viewController, attribute.Animated);
            return;
        }

        // then try to show child for the tabs
        if (TabBarViewController != null && TabBarViewController.ShowChildView(viewController))
        {
            return;
        }

        base.ShowChildViewController(viewController, attribute, request);
    }

我希望能节省一些人的时间。