Как правильно создать контроллер корневого представления в коде в Xamarin.iOS с MvvmCross 6? - PullRequest
0 голосов
/ 15 мая 2018

Я пытаюсь написать пользовательский интерфейс Xamarin.iOS в коде и следую этому учебному пособию по MS .К сожалению, я не могу найти способ установить мой MvxTabBarViewController (MainViewController) в качестве корневого контроллера.Создание экземпляра контроллера с помощью NullReferenceException.

Как правильно установить контроллер в качестве корневого контроллера в MvvmCross?


Мой AppDelegate выглядит следующим образом:

[Register(nameof(AppDelegate))]
public class AppDelegate : MvxApplicationDelegate<Setup, App>
{
    public override void FinishedLaunching(UIApplication application)
    {
        base.FinishedLaunching(application);
    }

    public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
    {
        Window = new UIWindow(UIScreen.MainScreen.Bounds);
        var controller = new MainViewController();
        Window.RootViewController = controller;
        Window.MakeKeyAndVisible();
        Debug.WriteLine("Set root view to MainViewController");
        return true;
    }
}

И контроллер представления должен быть root:

[MvxRootPresentation]
public partial class MainViewController : MvxTabBarViewController<MainViewModel>
{
    private UILabel label;
    //public MainViewController(IntPtr handle) : base(handle)
    //{
    //}

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
        Debug.WriteLine("Main View Controller loaded");
        AddLabel();
    }

    private void AddLabel()
    {
        label = new UILabel
        {
            Text = "testing",
            TranslatesAutoresizingMaskIntoConstraints = false
        };
        var lblConstraints = new[]
        {
            label.LeadingAnchor.ConstraintEqualTo(anchor:this.View.SafeAreaLayoutGuide.LeadingAnchor, constant:20.0f),
            label.WidthAnchor.ConstraintEqualTo(label.IntrinsicContentSize.Width),
            label.TopAnchor.ConstraintEqualTo(anchor:this.View.SafeAreaLayoutGuide.TopAnchor, constant:20.0f),
            label.HeightAnchor.ConstraintEqualTo(label.IntrinsicContentSize.Height)
            };
        View.AddSubview(label);
    }
}

Трассировка стека исключений:

  at MvvmCross.Mvx.Resolve[TService] () [0x00006] in <8a077b300d9c484ab0471c2d21c3cb26>:0 
  at MvvmCross.Platforms.Ios.Views.MvxBindingViewControllerAdapter..ctor (MvvmCross.Platforms.Ios.Views.Base.IMvxEventSourceViewController eventSource) [0x00034] in <8a077b300d9c484ab0471c2d21c3cb26>:0 
  at MvvmCross.Platforms.Ios.Views.MvxViewControllerAdaptingExtensions.AdaptForBinding (MvvmCross.Platforms.Ios.Views.Base.IMvxEventSourceViewController view) [0x00007] in <8a077b300d9c484ab0471c2d21c3cb26>:0 
  at MvvmCross.Platforms.Ios.Views.MvxBaseTabBarViewController..ctor () [0x00006] in <8a077b300d9c484ab0471c2d21c3cb26>:0 
  at MvvmCross.Platforms.Ios.Views.MvxTabBarViewController..ctor () [0x00000] in <8a077b300d9c484ab0471c2d21c3cb26>:0 
  at MvvmCross.Platforms.Ios.Views.MvxTabBarViewController`1[TViewModel]..ctor () [0x00000] in <8a077b300d9c484ab0471c2d21c3cb26>:0 
  at PushNotifTest.iOS.Views.Main.MainViewController..ctor () <0x13d7f4970 + 0x0004a> in <1d11ff58113e46f6a5a9245eccb8c13f>:0 
  at PushNotifTest.iOS.AppDelegate.FinishedLaunching (UIKit.UIApplication application, Foundation.NSDictionary launchOptions) [0x00017] in /Users/dominik/Projekty/PushNotifTest/src/PushNotifTest.iOS/AppDelegate.cs:28 
  at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr)
  at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.11.0.280/src/Xamarin.iOS/UIKit/UIApplication.cs:79 
  at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0002c] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.11.0.280/src/Xamarin.iOS/UIKit/UIApplication.cs:63 
  at PushNotifTest.iOS.Application.Main (System.String[] args) [0x00001] in /Users/dominik/Projekty/PushNotifTest/src/PushNotifTest.iOS/Main.cs:9 

1 Ответ

0 голосов
/ 15 мая 2018

Вы должны позволить MvvmCross сделать это за вас.Обычно вы указываете, какая ViewModel должна отображаться первой в вашем IMvxAppStart производном классе.

public class AppStart : IMvxAppStart
{
    private readonly IMvxNavigationService _navigationService;

    public AppStart(IMvxNavigationService navigationService)
    {
        _navigationService = navigationService;
    }

    public void Start(object hint = null)
    {
        try
        {
            _navigationService.Navigate<MainViewModel>().GetAwaiter().GetResult();
        }
        catch (System.Exception e)
        {
        }
    }
}

Где MainViewModel будет ViewModel, связанной с вашим ViewController, который является MvxTabBarViewController.

Затем просто выполните обычную церемонию в AppDelegate, которую MvvmCross ожидает от вас:

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

    var setup = new Setup(this, Window);
    setup.Initialize();

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

    Window.MakeKeyAndVisible();

    return true;
}

Таким образом, Setup раскручивает контейнер IoC и другие связанные службы MvvmCross.Затем ваш IMvxAppStart перейдет к первому ViewController.

В зависимости от того, как вы приписываете свой MvxTabBarViewController, он будет заключен в NavigationViewController.Вы можете управлять им с помощью MvxRootPresentationAttribute.

[MvxRootPresentation(WrapInNavigationController = true)]
public partial class MainViewController : MvxTabBarViewController<MainViewModel>

EDIT:

Вместо обычной церемонии MvvmCross 6.0 упростил эту часть.Поэтому удалите тело AppDelegate и создайте его следующим образом:

[Register("AppDelegate")]
public partial class AppDelegate : MvxApplicationDelegate<MvxIosSetup<App>, App>
{
}

В вашем Ядре у вас есть класс App, который реализует MvxApplication.Здесь вызовите RegisterAppStart<TViewModel>() в переопределении Initialize():

public class App : MvxApplication
{
    public override void Initialize()
    {
        RegisterAppStart<RootViewModel>();
    }

Тогда не создавайте свой собственный класс AppStart.Вы можете выполнить запуск пользовательского интерфейса в Startup() в классе App.

...