0

我有一个UITableView名为 WaitTableView 的控制器。它只有一个单元格,这是UITableViewCell该类的代码:

    public class TableViewWaitCell : UITableViewCell
    {
        public UIActivityIndicatorView activityIndicator = new UIActivityIndicatorView(UIActivityIndicatorViewStyle.Gray);
        public UILabel lblLoading = new UILabel();

        public TableViewWaitCell(UITableViewCellStyle style, string reuseIdentifier) : base (style, reuseIdentifier)
        {
            this.SelectionStyle = UITableViewCellSelectionStyle.None;
        }

        ~TableViewWaitCell(){
            System.Console.WriteLine("TableViewWaitCell.~TableViewWaitCell");
            lblLoading = null;
            activityIndicator = null;   
            System.GC.Collect();
        }
       protected override void Dispose (bool disposing){
            System.Console.WriteLine("TableViewWaitCell.Dispose");
            lblLoading = null;
            activityIndicator = null;
            base.Dispose (disposing);
            GC.Collect();
        }

        public override void Draw (System.Drawing.RectangleF rect)
        {
            base.Draw (rect);

            var context = UIGraphics.GetCurrentContext();
            var gradient = new CGGradient(
            CGColorSpace.CreateDeviceRGB(),
                new float[] { 1f, 1f, 1f, 1f,
                              0.68f, 0.68f, 0.72f, 1f },
                new float[] { 0f, 1f } );
                context.DrawLinearGradient(gradient,
                    new PointF(rect.X+rect.Width/2, rect.Y),
                    new PointF(rect.X+rect.Width/2, rect.Y+rect.Height),
                    CGGradientDrawingOptions.DrawsAfterEndLocation);

            var activityIndicatorViewFrame = new RectangleF(rect.X + rect.Width/2-10, rect.Y+10, 20, 20);
            this.activityIndicator  .Frame = activityIndicatorViewFrame;
            this.activityIndicator.AutoresizingMask = UIViewAutoresizing.FlexibleDimensions;
            this.activityIndicator.StartAnimating();
            this.AddSubview(this.activityIndicator);

            var labelFrame = new RectangleF(rect.X, rect.Y+10+activityIndicatorViewFrame.Height, rect.Width, 35);
            this.lblLoading.Frame = labelFrame;
            this.lblLoading.AutoresizingMask = UIViewAutoresizing.FlexibleDimensions;
            this.lblLoading.TextColor = UIColor.Black;
            this.lblLoading.BackgroundColor = UIColor.Clear;
            this.lblLoading.TextAlignment = UITextAlignment.Center;
            this.lblLoading.Text = Dictionary.GetValue("Loading");
            this.AddSubview(this.lblLoading);
        }
    }

这是ViewWillDisappear主要的方法UIViewController

        public override void ViewWillDisappear (bool animated)
    {
        Console.WriteLine("SpotlightView.ViewWillDisappear");
        if(this.PopoverController!=null)
            this.PopoverController.Dismiss(true);
        this.PopoverController = null;
        this.tableView.RemoveFromSuperview();
        this.WaitTableView.RemoveFromSuperview();
        this.searchBar.RemoveFromSuperview();
        this.tableView.Source = null;
        this.tableView.Dispose();
        this.tableView = null;
        this.WaitTableView.Source = null;
        this.WaitTableView.Dispose();
        this.WaitTableView = null;
        this.searchBar.Delegate = null;
        this.searchBar.Dispose();
        this.searchBar = null;

        base.ViewWillDisappear (animated);
    }

我的问题是我的细胞的析构函数和 Dispose 都没有被调用。当我运行 heapshot 时,TableViewWaitCell 类的实例数量增加了我浏览我的应用程序。我不明白 Monotouch 是如何管理细胞生命周期的,我做错了什么?

4

2 回答 2

2

在您共享的代码中,我没有看到任何会导致此问题的内容。但是,您没有显示单元是如何构造和存储的。您的对象可能会通过您未在示例代码中显示的根保持活动状态。我在下面创建了一个示例,显示了 Dispose 和正在调用的终结器。

使用模拟器可以快速收集表格视图和单元格。通常在第二次按下“显示表格”按钮后。

在设备上运行会显示不同的行为。表格和单元格不会立即收集。最简单的解释是 GC 被“调整”为仅在需要时运行。因此,如果您的应用程序没有使用太多内存,所有对象都将继续存在。

如示例中所示,您可以执行两件事来强制 GC 运行。

showTable.TouchUpInside += delegate {
    navController.PushViewController (new MyViewController (), true);
    // Not a great idea to call Collect but you could to force it.
    // GC.Collect ();
};

allocate.TouchUpInside += delegate {
    // Trigger the GC by creating a bunch of objects
    System.Collections.Generic.List<object> list = new System.Collections.Generic.List <object> ();
    for (int i=0; i<2048; i++)
    {
        list.Add (new object ());
    }
};

首先你可以调用 GC.Collect。但是我不建议这样做。当你让它运行时,GC 会运行得最好。(在大多数情况下。) 何时可以调用 GC.Collect?

其次,继续编写代码,让 GC 决定什么是最好的。在示例中,我添加了另一个按钮,用于分配一堆对象并将它们添加到列表中。因此,如果您在表格视图和主视图之间切换几次,然后按几次分配按钮,您应该会看到终结器运行。

using System;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using MonoTouch.CoreGraphics;
using System.Drawing;

namespace delete20130320
{
    [Register ("AppDelegate")]
    public partial class AppDelegate : UIApplicationDelegate
    {
        UIWindow window;


        public override bool FinishedLaunching (UIApplication app, NSDictionary options)
        {
            window = new UIWindow (UIScreen.MainScreen.Bounds);

            var mainView = new UIViewController ();
            var showTable = UIButton.FromType (UIButtonType.RoundedRect);
            showTable.Frame = new System.Drawing.RectangleF (10, 10, 150, 35);
            showTable.SetTitle ("Show Table", UIControlState.Normal);

            var allocate = UIButton.FromType (UIButtonType.RoundedRect);
            allocate.Frame = new System.Drawing.RectangleF (10, 55, 150, 35);
            allocate.SetTitle ("Allocate", UIControlState.Normal);

            mainView.View.BackgroundColor = UIColor.White;
            mainView.View.Add (showTable);
            mainView.View.Add (allocate);

            var navController = new UINavigationController (mainView);

            showTable.TouchUpInside += delegate {
                navController.PushViewController (new MyViewController (), true);
                // Not a great idea to call Collect but you could to force it.
                // GC.Collect ();
            };

            allocate.TouchUpInside += delegate {
                // Trigger the GC by creating a bunch of objects
                System.Collections.Generic.List<object> list = new System.Collections.Generic.List <object> ();
                for (int i=0; i<2048; i++)
                {
                    list.Add (new object ());
                }
            };


            window.RootViewController = navController;

            window.MakeKeyAndVisible ();

            return true;
        }
    }

    public class MyViewController : UIViewController
    {
        UITableView _tableView;
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();
            _tableView = new UITableView (this.View.Bounds);
            View.Add (_tableView);

            _tableView.DataSource = new MyDataSource ();
        }

        ~MyViewController ()
        {
            // Bad practice to call other managed objects in finalizer
            // But for sample purposes it will be ok
            Console.WriteLine ("~MyViewController");
        }

        protected override void Dispose (bool disposing)
        {
            // Bad practice to call other managed objects in Dispose
            // But for sample purposes it will be ok
            Console.WriteLine ("MyViewController.Dispose");
            base.Dispose (disposing);
        }

        class MyDataSource : UITableViewDataSource
        {
            public override int RowsInSection (UITableView tableView, int section)
            {
                return 1;
            }

            public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
            {
                var cell = tableView.DequeueReusableCell ("SomeUniqueString");
                if (cell != null)
                    return cell;

                return new TableViewWaitCell (UITableViewCellStyle.Default, "SomeUniqueString");
            }
        }
    }

    public class TableViewWaitCell : UITableViewCell
    {
        public TableViewWaitCell(UITableViewCellStyle style, string reuseIdentifier) : base (style, reuseIdentifier)
        {
            this.SelectionStyle = UITableViewCellSelectionStyle.None;
            this.TextLabel.Text = "Something";
        }

        ~TableViewWaitCell()
        {
            // Bad practice to call other managed objects in finalizer
            // But for sample purposes it will be ok
            System.Console.WriteLine("TableViewWaitCell.~TableViewWaitCell"); 
            // Avoid forcing the GC
            //System.GC.Collect();
        }
        protected override void Dispose (bool disposing)
        {
            // Bad practice to call other managed objects in Dispose
            // But for sample purposes it will be ok
            System.Console.WriteLine("TableViewWaitCell.Dispose");
            base.Dispose (disposing);
            //GC.Collect();
        }
    }
}
于 2013-03-21T04:47:47.323 回答
0

问题来自一个 EventHandler,它引用了我的视图控制器的一个方法,从而阻止了我的单元格和我的控制器的集合。

于 2013-04-04T13:43:36.680 回答