收到内存警告后,UITableViewController为空

时间:2012-03-28 18:04:06

标签: c# ios xamarin.ios uitableview

我通过继承UITableViewControllerUITableViewSource(不是UITableViewDataSource !!!)在MonoTouch中绘制表格视图。在我的视图控制器的构造函数中,我设置了表视图源:

TableView.Source = new CustomTableViewSource();

在我的CustomTableViewSource中,我正在构建表格视图的单元格。除非我在iPhone模拟器中模拟内存警告,否则它的工作效果很好。如果视图被隐藏(例如,选中标签栏中的其他视图控制器),当我回来时,表格视图只是空白(白色背景,不再有桌面视图)。

但是,我在DidReceiveMemoryWarning回调中什么也没做。我还尝试再次设置TableViewSource viewWillAppear(如果收到内存警告),但没有更多的成功......

是垃圾收集器问题吗?我知道在接收内存警告时会调用GC.Collect。也许垃圾收集器只是丢掉我的视图,我需要再次完全显示它?

3 个答案:

答案 0 :(得分:2)

您应该在ViewDidLoad方法中而不是在构造函数中初始化表源。加载视图控制器时调用该方法,然后每次在内存警告后需要重新创建控制器视图时调用该方法。

我做了一些测试,在内存警告后得到了类似的结果。但是,我只获得一个空表视图。当我再次在ViewWillAppear中设置表源时,表中会正常填充数据。

您在ViewWillAppear中的实现不起作用的事实让我觉得该方法甚至没有被调用。如果是这种情况,我猜你的表视图在需要的时候没有被重新创建。

在使用不是从XIB文件创建视图的控制器时,在某些情况下会发生这种情况。在这种情况下,您应该在LoadView方法中创建视图(不调用base.LoadView()):

public override void LoadView()
{
    this.View = new UITableView(UIScreen.MainScreen.ApplicationFrame); //or something similar
}

我遇到了类似的问题(没有重新创建的表视图),包含导航控制器的复杂层次结构,包含导航控制器,包含视图控制器等。当我提供LoadView方法时,问题就解决了。

我猜对了;)

答案 1 :(得分:1)

当收到内存警告时,您将调用GC.Collect()是对的。这是来自操作系统的严重警告,MonoTouch将尝试释放它自己的内存(如果可能)。你可以通过覆盖DidReceiveMemoryWarning来扩展它,这样你的应用程序也可以释放它并不是绝对需要的任何内存。

对GC的调用(与任何其他调用一样)意味着可以收集和释放未引用的每个对象。现在不应该收集您的CustomTableViewSource实例(除非您的TableView是)。如有疑问,可以通过为类型添加终结器来检查这一点,例如

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

然而,您的CustomTableViewSource 中的对象可以收集(如果未引用),因为您的表的其他部分(UI)可能是。没有看到源代码就无法分辨。

我建议你试着找出被释放的内容,然后从那里你应该看到需要保留引用(避免被收集)或需要重新创建的内容(如果某些实例是故意释放的)。

答案 2 :(得分:1)

总而言之,我的解决方案是:

public class LoginViewController : UITableViewController
{
  LoginDataSource m_loginDataSource;

  public LoginViewController(UITableViewStyle withStyle) : base(withStyle)
  {
   m_loginDataSource = new LoginDataSource(this);
  }

  public override void LoadView()
  {
    this.View = new UITableView(UIScreen.MainScreen.ApplicationFrame,  UITableViewStyle.Grouped);
  }

  public override void ViewDidLoad ()
  {
    base.ViewDidLoad ();
    TableView.Source = m_loginDataSource;
  }
}