我有一个具有 UITabBarController 的 MonoTouch 应用程序,每个选项卡都是 UINavigationController。其中一些包装了一个 UIViewController,它添加了一个 UITableView 和一个 UIToolbar,而另一些包装了一个 DialogViewController。
到目前为止,我还没有过多关注内存/视图管理(我主要是在模拟器中运行),但是当我开始在真实设备上进行测试时,我注意到由于内存不足而导致的一些故障(例如,应用程序被终止,我从日志中发现 DidReceiveMemoryWarning 在此之前被调用)。其他时候,我注意到应用程序响应的长时间停顿,我认为这是由于 GC 周期造成的。
到目前为止,我一直假设我推送到导航堆栈的每个 DialogViewController 都会清理它的视图和其他在我弹出它时分配的东西。但我开始意识到这可能并不容易,我需要开始调用 Dispose() 。
是否有关于如何使用 MonoTouch 和 MT.D 管理资源和内存的最佳实践?具体来说:
- 弹出后是否需要在 DialogViewController 上调用 Dispose?如果是这样,最好在哪里执行此操作?(ViewDidUnload?DidReceiveMemoryWarning?析构函数?)
- DVC 是否会自动处理传递给它的 RootElement 之类的对象,还是我需要担心这个?它作为渲染表格单元格(例如 StyledStringElement)的一部分加载的 UIImages 怎么样?
- 有没有我应该调用 GC.Collect() 来更好地分隔集合的地方,以便在发生 GC 时不会受到响应的影响?
- 分代垃圾收集器是否有助于解决交互问题,是否足够稳定,可以在生产应用程序中使用?(我相信它在 MonoDevelop 3.0.2 / MT 4.3.3 中仍然被称为“实验性”)
- 我需要在 DidReceiveMemoryWarning 中做些什么来降低 iOS 拍摄我的应用程序的可能性?由于每个不可见的视图控制器似乎都收到了这个调用,我假设我应该清理那个视图控制器的资源......我应该做我在 ViewDidUnload 中做的同样的事情吗?
- 我似乎没有调用我的 ViewDidUnload(即使在我收到 DidReceiveMemoryWarning 之后)。事实上,我不记得曾经在我的日志中看到过它。如果 iOS 总是在 DidReceiveMemoryWarning 之后调用我的 ViewDidUnload,我可以在 ViewDidUnload 中进行所有清理......在 ViewDidUnload 和 DidReceiveMemoryWarning 之间划分清理责任的最佳方法是什么?
对于这个问题的一般性质,我深表歉意——这似乎是一个很好的白皮书主题,但我找不到任何......
更新:为了使问题更具体:在使用 Instruments 和 Xamarin Heapshot 分析器之后,我很清楚当用户弹出导航堆栈时我正在泄漏 UIViewControllers。Rolf 提交了一个错误为此,它有两个重复,所以这不仅仅是我一个真正的问题。不幸的是,我还没有为泄露的 UIViewControllers 找到一个好的解决方法——我还没有找到一个对它们调用 Dispose() 的好地方。释放 ViewDidLoad 分配的资源的自然位置是在 ViewDidUnload 消息中,但它从未在模拟器上被调用,因此我的内存占用不断增长。在设备上,我确实看到了 DidReceiveMemoryWarning,但我不愿意使用它作为释放我的 viewcontroller 及其资源的地方,因为我不能保证 iOS 会真正卸载我的视图,因此不能保证我的 ViewDidLoad 会再次被调用要么(导致 ViewDidAppear 需要针对其底层资源被处置的情况进行防御性编码)。我'