iosuiviewcontrollernavigationmvvmcrossparentviewcontroller

How to go back to the previous controller in one click after observing several controllers of the same type on iOS?


We are using MvvmCross 4.4.0 on the our iOS project and I faced the following problem:

Diagram:

Catalogue --ConcreteItem--> Item1 --MoreItems--> Item2 --MoreItems-->

Item3 --BackNavButton--> Catalogue.

I am doing the following thing in the Custom ViewPresenter:

                var topViewController = ParentRootViewController.TopViewController;
                ParentRootViewController.PushViewController(currentViewController, needAnimation);

                if (topViewController.GetType() == currentView.GetType()
                    && /*Logic to determine if its correct view types*/)
                {
                    topViewController.RemoveFromParentViewController();
                    topViewController.Dispose();
                }

And actually it works until I didn't return to the "Catalogue" page. The problem is that I need to click back button so many times I had clicked "More" button on "Item" page. Also if we use custom back button with such code in both "Catalogue" and "Item" pages:

  if (NavigationController?.NavigationBar?.BackItem != null)
        {
             var backbutton = new UIBarButtonItem(" ",
                                                 UIBarButtonItemStyle.Plain,
                                                 (sender, e) => { NavigationController?.PopViewController(true); })
            {
                Image = UIImage.FromBundle("BackButtonImage")
            };

            NavigationItem.LeftBarButtonItem = backbutton;
        }

then app crashes when clicking "Back" NavButton on "Catalogue" page with in lambda

(sender, e) => { NavigationController?.PopViewController(true);

The disposed object ItemPageViewController.

The question is : How to correctly implement "SingleTop" page in MvvmCross?

Or

How to fix this problem?

P.S.: If from MvxPresenter remove line

topViewController.Dispose();

then in custom lambda would throw NullReferenceException.

P.P.S.: I believe it the problem that I don't remove controller from navigation stack. I have tried to remove controllers in Custom View Presenter, but, firstly, it is null there sometimes, and even with null check nothing helped.


Solution

  • UINavigationController has a function PopToViewController(UIViewController viewController, bool animated);

    Instead of removing every ViewController when the views are of the same type, you could pop to the ViewController Catalogue when the backbutton is pressed.

    UINavigationController has a property ViewControllers that we can use to find CatalogueViewController.

    Since you're using MvvmCross we'll check for the ViewModel type.

    var catalogueController = NavigationController.ViewControllers.First(c => 
        ((IMvxIosView)c).ViewModel.GetType() == typeof(CatalogueViewModel));
    

    Now you can use the function PopToViewController to close all the views untill CatalogueController

    CurrentNavigationController.PopToViewController(catalogueController, true);