MonoTouch.Dialog DialogViewController not disposed when Root is non-null

Hi, I'm having a weird problem. I'm using Subclasses of DialogViewController for a multi-page interview. Each page presents a number of fields that can be edited, and hitting save in the upper right pushes the next page onto the NavigationController. It seemed to be working fine, but it became apparent that backing out and repeating the interview leaks memory. I created a simple test case that properly cleans up the button event for the navigation item. In this example, Dispose is called when the second controller is popped, but only if I don't set Root to something other than null (i.e. this works as expected if I comment the Root = ... line). Here's the code. Please tell me I'm missing something stupid.

public class TestViewController : DialogViewController
{
int mPage;

    public TestViewController (int page) : base (null, true)
    {
        mPage = page;

        Root = new RootElement ("Testing") {
            new Section () {
                new StringElement ("Page: " + mPage)
            }
        };
    }

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();

        NavigationItem.RightBarButtonItem = new UIBarButtonItem (UIBarButtonSystemItem.Play);
    }

    public override void ViewWillAppear (bool animated)
    {
        base.ViewWillAppear (animated);

        NavigationItem.RightBarButtonItem.Clicked += OnClicked;
    }

    public override void ViewDidDisappear (bool animated)
    {
        base.ViewDidDisappear (animated);

        NavigationItem.RightBarButtonItem.Clicked -= OnClicked;
    }

    private void OnClicked(object sender, EventArgs e)
    {
        NavigationController.PushViewController(new TestViewController(mPage + 1), true);
    }

    protected override void Dispose (bool disposing)
    {
        base.Dispose (disposing);
    }
}

Posts

  • BrianCooleyBrianCooley USMember

    With a little more testing, I was able to get them to dispose by putting int navLength = NavigationController.ViewControllers.Length; in ViewWillAppear (I think anything that accesses the ViewControllers property will do the same). Without that, that aren't popped until a new controller is pushed back on. Similarly, if I want to kill the whole navigation stack (from a leftbarbuttonitem click) I had to clear the stack with NavigationController.ViewControllers = new UIViewController[] {}; to get it to dispose. I guess this works, but it seems pretty terrible. I thought this was fixed in 3.0 with the new reference counting?

  • SebRichardsSebRichards GBMember

    I managed to come up with:

        public override void ViewDidDisappear(bool animated) {
    
            base.ViewDidDisappear(animated);
    
            // If removed from view stack
            if (NavigationController == null) {
    
                // Force dispose
                if (Root != null) {
                    Root.TableView.Dispose();
                    Root.Dispose();
                }
            }
        }
    
Sign In or Register to comment.