Search code examples
ios8mvvmcross

MVVM Cross Resolve IMvxTouchViewCreator fails iOS 8


Calling Mvx.Resolve does not work for me when I deploy to iOS 8 (device or simulator) but works fine when I deploy to iOS 7.1 (device or simulator). I receive the following error:

"Cirrious.CrossCore.Exceptions.MvxIoCResolveException: Failed to resolve type Cirrious.MvvmCross.Touch.Views.IMvxTouchViewCreator"

I tried running the TwitterSearch example (because it also resolves IMvxTouchViewCreator) and it has no trouble in iOS 8. For iOS 7.1 this call resolves to the class MvxTouchViewsContainer (same in iOS 8 in the TwitterSearch example). Along the way, I tried explicity registering the type 'MvxTouchViewsContainer' for 'IMvxTouchViewCreator' in Setup.cs. This got me past the Resolve exception, but then when I try to create my FirstView:

var creator = Mvx.Resolve<IMvxTouchViewCreator>();
var viewController = (UIViewController)creator.CreateView(new FirstViewModel());

I get an exception indicating that it cannot

"System.Collections.Generic.KeyNotFoundException: Could not find view for .FirstViewModel"

Is there a way in iOS to examine the ViewModel to View mappings like in this android example?


Solution

  • I work with jyarnott and we did resolve the issues.

    In case it's helpful for anyone else, here's what we did.

    We have a custom presenter that loads a custom view controller and assigns it to RootViewController.

    public class ShellViewPresenter : MvxBaseTouchViewPresenter
    {
        private readonly ShellViewController _shellViewController;
    
        private readonly Stack<UIViewController> _navStack = new Stack<UIViewController>();
    
        private MenuViewModel _menuViewModel;
    
        public ShellViewPresenter( UIWindow window )
        {
            _shellViewController = new ShellViewController();
            window.RootViewController = _shellViewController;
        }
    }
    

    In iOS 7 it appears that ViewDidLoad of the ShellViewController was called when our first view was navigated to (after all the plug ins and containers were loaded), but in iOS 8, the ViewDidLoad of ShellViewController was called immediately upon being set to RootViewController. This allowed our code to work in iOS 7 but not in iOS 8.

    Here's the original ViewDidLoad method

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
    
            var viewController = (UIViewController) Mvx.Resolve<IMvxTouchViewCreator>().CreateView( new FirstViewModel() );
            LoadViewController( viewController );
    
            View = _shellView;
        }
    

    The solution was to add a Mvx.CanResolve() condition around the Mvx.Resolve() call, so it would work as expected in both versions.

    Here's the final version that resolved the issue.

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
    
            if ( Mvx.CanResolve<IMvxTouchViewCreator>() )
            {
                var viewController = (UIViewController) Mvx.Resolve<IMvxTouchViewCreator>().CreateView( new FirstViewModel() );
                LoadViewController( viewController );
            }
    
            View = _shellView;
        }