Quantcast
Channel: Recent Threads — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 204402

Using NavigationController property prevents UIViewController collection

$
0
0

This is a follow on from here http://forums.xamarin.com/discussion/12005/uiviewcontroller-never-garbage-collected-with-derived-uiview in which I'm trying to sort out a bunch of issues relating to view controllers not getting released.

This time, it seems that after accessing UIViewController.NavigationController you must Dispose the returned object. For example:

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

    if (false)
    {
        // This works
        using (var nav = NavigationController)
        {
            float headerHeight = nav.NavigationBar.Frame.Bottom;    
        }
    }
    else
    {
        // This causes the view controller to not be GC'ed.
        float headerHeight = this.NavigationController.NavigationBar.Frame.Bottom;  
    }
}

Really? Surely it shouldn't be necessary to Dispose the return value of a property get? Is there a better workaround?

See below for a full project that demonstrates the issue:

using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System.Drawing;

namespace gctest
{
    class TypedWeakReference<T>
    {
        public TypedWeakReference(T target)
        {
            _wr = new WeakReference(target);
        }

        public T Target
        {
            get { return (T)_wr.Target; }
        }

        WeakReference _wr;
    }

    class OtherViewController : UIViewController
    {
        public OtherViewController()
        {
            this.View = new UIView();

            this.View.BackgroundColor = UIColor.Green;

            var button = new UIButton(new RectangleF(20, 40, 280, 60));
            button.SetTitle("Dismiss This", UIControlState.Normal);
            button.BackgroundColor = UIColor.Orange;
            this.View.AddSubview(button);

            var weakThis = new TypedWeakReference<OtherViewController>(this);
            button.TouchUpInside += (s, a) => {
                weakThis.Target.DismissViewController(true, null);
            };
        }

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

            if (false)
            {
                // This works
                using (var nav = NavigationController)
                {
                    float headerHeight = nav.NavigationBar.Frame.Bottom;    
                }
            }
            else
            {
                // This causes the view controller to not be GC'ed.
                float headerHeight = this.NavigationController.NavigationBar.Frame.Bottom;  
            }
        }

        ~OtherViewController()
        {
            Console.WriteLine("OtherViewController finalized");
        }

    }

    class MainViewController : UIViewController
    {
        public MainViewController()
        {
            this.View.BackgroundColor = UIColor.Yellow;

            var button = new UIButton(new RectangleF(20, 40, 280, 60));
            button.SetTitle("Show Other", UIControlState.Normal);
            button.BackgroundColor = UIColor.Orange;
            button.TouchUpInside += (sender, e) => {

                var vc = new OtherViewController();
                PresentViewController(new UINavigationController(vc), true, null);

            };
            this.View.AddSubview(button);

            button = new UIButton(new RectangleF(20, 140, 280, 60));
            button.SetTitle("GC Now", UIControlState.Normal);
            button.BackgroundColor = UIColor.Orange;
            button.TouchUpInside += (sender, e) => {

                System.GC.Collect();

            };
            this.View.AddSubview(button);
        }
    }

    [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 MainViewController();
            window.MakeKeyAndVisible();

            return true;
        }
    }
}

Viewing all articles
Browse latest Browse all 204402

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>