2010-10-13 18 views
2

我在iPhone应用程序中遇到内存问题。我正在使用MonoTouch。我通过使用静态实例计数器来追究这个问题。这个问题与模态视图控制器有关。当我从根视图控制器导航到第一级视图控制器并返回时,我发现第一级视图控制器是垃圾收集的。但是当我通过调用PresentModalViewController来制作第一级viewcontroller模式时,我通过调用DismissModalViewControllerAnimated返回,我发现第一级viewcontroller不是垃圾收集。即使我打电话给GC.Collect()UIViewController在启动模式时不会收集垃圾

为什么不呢?难道我做错了什么?

确保视图控制器发布的最佳做法是什么?

partial class RootViewController : UITableViewController 
{ 
    static int instanceCount; 
    static int nextId; 
    int instanceId; 

    public RootViewController (IntPtr handle) : base(handle) 
    { 
     instanceCount++; 
     instanceId = nextId++; 
     Console.WriteLine(string.Format("RootViewController #{0} Count={1}", instanceId, instanceCount)); 
    } 

    public override void ViewDidLoad() 
    { 
     base.ViewDidLoad(); 
     Title = "Root"; 
     NavigationItem.RightBarButtonItem = new UIBarButtonItem("ModalVC", UIBarButtonItemStyle.Plain, 
      delegate 
      { 
       var firstlevelVc = new FirstLevelViewController(); 
       PresentModalViewController(new UINavigationController(firstlevelVc), true); 
      }); 

     NavigationItem.LeftBarButtonItem = new UIBarButtonItem("PushVC", UIBarButtonItemStyle.Plain, 
      delegate 
      { 
       var firstlevelVc = new FirstLevelViewController(); 
       NavigationController.PushViewController(firstlevelVc, true); 
      }); 
    } 

    public override void ViewDidAppear (bool animated) 
    { 
     base.ViewDidAppear (animated); 
     GC.Collect(); 
    } 

    ~RootViewController() 
    { 
     instanceCount--; 
     Console.WriteLine(string.Format("RootViewController #{0} Count={1}", instanceId, instanceCount)); 

    } 
} 
public partial class FirstLevelViewController : UIViewController 
{ 
    static int instanceCount; 
    static int nextId; 
    int instanceId; 
    public FirstLevelViewController (IntPtr handle) : base(handle) 
    { 
     Initialize(); 
    } 

    [Export("initWithCoder:")] 
    public FirstLevelViewController (NSCoder coder) : base(coder) 
    { 
     Initialize(); 
    } 

    public FirstLevelViewController() : base("FirstLevelViewController", null) 
    { 
     Initialize(); 
    } 

    void Initialize() 
    { 
     instanceCount++; 
     instanceId = nextId++; 
     Console.WriteLine(string.Format("FirstLevelViewController #{0} Count={1}", instanceId, instanceCount)); 
    } 

    public override void ViewDidLoad() 
    { 
     base.ViewDidLoad(); 
     Title = "1. level"; 

     NavigationItem.RightBarButtonItem = new UIBarButtonItem("Dismiss modal", 
                   UIBarButtonItemStyle.Plain, 
                   delegate { ParentViewController.DismissModalViewControllerAnimated(true); }); 

    } 

    ~FirstLevelViewController() 
    { 
     instanceCount--; 
     Console.WriteLine(string.Format("FirstLevelViewController #{0} Count={1}", instanceId, instanceCount)); 

    } 
} 
+0

我不能复制这个,但我没有你的xibs或调用代码。您可以向我发送整个项目,或者在http://monotouch.net/Support上提交错误消息吗? – 2010-11-04 15:09:08

回答

0

终结(〜方法)当一个对象引用计数器变为0被调用,你确定你没有一个参考的地方给你使用的UIViewController?为了确保我没有引用并确保删除GC,我实现了IDisposable和Dispose方法,调用它并在那里进行必要的清理(从内部集合等中删除所有对象),然后设置原始变量为空。所以它看起来像:

MyUIViewController cntrl = new MyUIViewController();

...做一些东西

//完成 cntrl.Dispose时(); cntrl = null;

就是这样。

顺便说一句。我相信你不应该经常自己调用GC.Collect,因为它会停止所有线程并只进行清理,所有工作都会停止,并且资源非常繁重。

希望它有帮助。

+0

如果存在对FirstLevelViewController的引用,它可能来自使用语句PresentModalViewController(new UINavigationController(firstlevelVc),true)创建的UINavigationController。但据我所见,navigationcontroller无法访问。 – 2010-10-13 21:58:13

+0

我只使用终结器来实现实例计数和跟踪,我只使用GC.Collect()来证明我的观点。 – 2010-10-13 21:58:48

+1

而你如何解雇模态控制器?该模板将使用this.ParentViewController.DismissModalViewControllerAnimated从子控件调用它到顶层控件。称它为自己的孩子,可能会导致这种情况。只是一个想法。 – 2010-10-13 22:13:04

0

如果您想手动处置控制器,您可以调用Dispose。