UITableViewController在收到内存警告后为空
本文关键字:警告 内存 UITableViewController | 更新日期: 2023-09-27 18:29:22
我正在MonoTouch中通过子类化UITableViewController
和UITableViewSource
(而不是UITableViewDataSource
!!)绘制一个表视图。在我的视图控制器的构造函数中,我设置了这样的表视图源:
TableView.Source = new CustomTableViewSource();
在我的CustomTableViewSource
中,我正在构建表视图的单元格。除了我在iPhone模拟器中模拟内存警告时,它的工作效果很好。如果视图被隐藏(例如,选择了选项卡栏中的其他视图控制器),当我回来时,表视图只是空白(白色背景,不再有表视图)。
但是,我在DidReceiveMemoryWarning
回调中什么也没做。我还尝试在viewWillAppear
中再次设置TableViewSource
(如果收到内存警告),但没有成功。。。
这是垃圾收集器的问题吗?我知道GC.Collect
是在收到内存警告时调用的。也许垃圾收集器只是在丢弃我的视图,而我需要再次完全显示它?
您应该在ViewDidLoad方法中而不是在构造函数中初始化表源。该方法在加载视图控制器时调用,然后每次在内存警告后需要重新创建控制器的视图时调用。
我做了一些测试,在收到内存警告后,我得到了类似的结果。但是,我只得到一个空表视图。当我再次在ViewWillAppear中设置表源时,表中通常会填充数据。
ViewWillAppear中的实现不起作用,这让我认为该方法甚至没有被调用。如果是这样的话,我猜你的表视图在需要的时候不会被重新创建
在某些情况下,当您使用的控制器的视图不是从XIB文件创建的时,可能会发生这种情况。在这种情况下,您应该在LoadView方法中创建视图(不调用base.LoadView()):
public override void LoadView()
{
this.View = new UITableView(UIScreen.MainScreen.ApplicationFrame); //or something similar
}
我在包含导航控制器、视图控制器等的选项卡控制器的复杂层次结构中遇到了类似的问题(未重新创建的表视图)。当我提供LoadView方法时,问题得到了解决。
我猜不透了;)
您是对的,当收到内存警告时,将调用GC.Collect()
。这是来自操作系统的严重警告,MonoTouch将尝试释放自己的内存(如果可能的话)。您可以通过重写DidReceiveMemoryWarning
来扩展它,这样您的应用程序也可以释放它不绝对需要的任何内存。
这种对GC的调用(和其他调用一样)意味着可以收集和释放每个未被引用的对象。现在不应该收集CustomTableViewSource
实例(除非您的TableView
是)。如果有疑问,您可以通过添加类型的终结器来检查这一点,例如
~CustomTableViewSource ()
{
Console.WriteLine ("~CustomTableViewSource");
}
然而,作为CustomTableViewSource
的一部分的对象可以像表的其他部分(UI)一样被收集(如果没有被引用的话)。如果看不到源代码,就无法判断。
我建议你试着找出被释放的内容,然后你应该看看需要什么来保留引用(以避免它们被收集)或需要重新创建什么(如果某些实例是故意释放的)。
总之,我的解决方案是:
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;
}
}