2

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

  • I need to implement "Item" page with reference to the other "Item" page;
  • I need an instant back navigation from any "Item" page to the previous controller ("Catalogue" controller).

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.

Oleg Kosuakiv
  • 134
  • 13

1 Answers1

2

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);
Mark Verkiel
  • 1,207
  • 10
  • 21
  • 1
    Thanks, I did this and it worked. The only drawback is that I had do to use custom back button and specify the concrete type of parent controller which are dependencies. Bu I really wanted to have a generic solution. – Oleg Kosuakiv Jun 26 '18 at 12:07
  • 1
    You could create an interface, implement it on the `ViewModel` and search for `ViewModel` that implements that interface and pop to that `ViewController`. Then this solution would be more generic. – Mark Verkiel Jun 26 '18 at 12:15