UIView事件和垃圾收集

时间:2011-02-04 21:09:06

标签: garbage-collection xamarin.ios

我观察到可能影响任何程序内存消耗的东西,我想要一些想法。

我用UIViewController和UINavigationViewController创建了一个非常简单的测试项目。我推动我的ViewController,然后我弹出它。 GC完成它并且我的ViewController被释放(析构函数被调用)。但是,如果我创建一个UIButton并且我注册了它的一个事件(例如:TouchInsideUp),那么我的ViewController就不会被释放。我需要取消注册该事件才能释放我的ViewController。为了确保它不是计时问题,我的测试应用程序有一个调用GC.Collect()的按钮。

我不明白的是,如果可以从任何线程的堆栈或静态变量访问对象,它将保持活动状态。如果我的ViewController有资格进行垃圾收集,那么UIButton也将是。该事件不应导致ViewController保留在内存中,因为GC无法访问UIButton。在我的例子中,ViewController仅由NavigationController使用,因此一旦弹出它就应该总是被收集。

在新的探查器(单声道2.10)的帮助下,我可能会找到一个逻辑答案,但就目前而言,我很困惑。任何的想法?

已编辑:以下是一些有助于了解我案例的代码。

我的测试ViewController非常简单

public class TestViewController : UIViewController{
  ~TestViewController(){ Console.WriteLine("Finalizer called"); }

  public UIButton Button {get; set;}
  public override ViewDidLoad(){
    base.ViewDidLoad();

    // If I remove the event registering, my TestViewController is collected.
    Button = new UIButton();
    Button.TouchUpInside += ButtonTouchEventHandler;
    View.AddSubview(Button);
  }

  void ButtonTouchEventHandler(object sender, EventArgs e){}
}

我的MainWindow有一个NavigationController,它执行以下操作:

  1. 它推送了一个新的TestViewController实例(因此只有NavigationController具有对TestViewController实例的引用)
  2. TestViewController通过标准后退按钮弹出(如果我没有注册到TouchUpInside,则调用TestViewController的终结器)
  3. 当我返回MainWindow时,一个按钮允许我调用GC.Collect以确定。

1 个答案:

答案 0 :(得分:0)

是的,对象图有可能被锁定在这个模式中,我已经修复了MonoTouch的下一个主要版本(MonoTouch 4)