Paul Knopf
Paul Knopf

Reputation: 9776

Xamarin.iOS simple NavigationController memory leak

I had an issue in my project and attempted to create a sample project to reproduce it and I was able to.

https://bitbucket.org/theonlylawislove/xamarinnavigationcontrollermemoryleak

The issue is that, when I present a UINavigationController, the navigation controller or its root view controller never gets garbage collected. It DOES work in the iOS simulator though. Why does this memory leak only happen on the device? If you run the sample project on the device, you will never see the Console.WriteLine in the deconstructors called.

I am using XCode5 and Xamarin.iOS 7.0.4.171 (Business Edition)

Here is the AppDelegate I am using to demonstrate the leak.

[Register ("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
    UIWindow window;
    public override bool FinishedLaunching (UIApplication app, NSDictionary options)
    {
        window = new UIWindow (UIScreen.MainScreen.Bounds);
        window.RootViewController = new UINavigationController(new RootController ());
        window.MakeKeyAndVisible ();

        return true;
    }

    class RootController : UIViewController
    {
        public RootController ()
        {
            NavigationItem.RightBarButtonItem = new UIBarButtonItem("Present", UIBarButtonItemStyle.Bordered, (o,e) => {
                PresentViewController(new NavigationController(), true, new NSAction(() => {}));
            });
        }
    }

    class NavigationController : UINavigationController
    {
        public NavigationController ()
            :base(new TestController())
        {

        }

        ~NavigationController()
        {
            Console.WriteLine("~NavigationController");
        }

        class TestController : UIViewController
        {
            ~TestController()
            {
                Console.WriteLine("~TestController");
            }

            public override void ViewDidAppear (bool animated)
            {
                base.ViewDidAppear (animated);
                Task.Factory.StartNew (() => {
                    Thread.Sleep(2000);
                    NSThread.MainThread.InvokeOnMainThread(new NSAction(() => {
                        DismissViewController(true, new NSAction(() => {

                        }));
                    }));
                });
            }
        }
    }

}

Upvotes: 4

Views: 515

Answers (1)

miguel.de.icaza
miguel.de.icaza

Reputation: 32694

This is merely a side effect of the conservative collector, there might be some junk on the stack, but using your application will eliminate the junk and allow the object to be released.

If you use SGen, which uses a precise system, you will see the object vanish right away.

Upvotes: 3

Related Questions