我们正在实现一个似乎存在重大内存泄漏的应用程序。例如,我们有一个视图及其对应的视图模型,该视图模型在单分析器中注册了 38 次,但它应该被垃圾回收。我们有很多自定义控件等,但是应该在哪里处理这些 - 从 ios 6 开始不再调用 viewdidunload 那么我们应该在哪里进行清理?
问候
我们正在实现一个似乎存在重大内存泄漏的应用程序。例如,我们有一个视图及其对应的视图模型,该视图模型在单分析器中注册了 38 次,但它应该被垃圾回收。我们有很多自定义控件等,但是应该在哪里处理这些 - 从 ios 6 开始不再调用 viewdidunload 那么我们应该在哪里进行清理?
问候
这是一个很大的问题……对于一般情况,不容易回答。
一般来说,如果您编写了简单的 ViewModel 和简单的 View,那么您将不会遇到任何内存泄漏。
但是,如果您有引用 ViewModel 的 View,而后者又具有以某种方式引用 View 的回调,那么很可能会发生内存泄漏——尤其是当您的 View Model 订阅服务上的事件时。
一种特别糟糕的情况是 ObjC 和 C# 都引用了对象。在http://forums.xamarin.com/discussion/97/correct-way-to-pop-a-dialogviewcontroller-mine-are-staying-in-memory上对此进行了一些讨论,其中也提到了我们曾经遇到的问题SQL 位示例 - https://github.com/slodge/MvvmCross/issues/19
您当前的泄漏可能不是这种情况,但值得阅读 Rolf 的回答 - http://forums.xamarin.com/discussion/comment/535/#Comment_535 - 几次 - 这不是入门级解释,但它最终是有道理的!
因此,为了解决您当前的问题...
找出泄漏的内容
找出原因 - 是什么保留了参考资料。
修理它。
关键是在对 3 进行错误修复之前投入大量精力来研究 1 和 2。在不真正知道“它”是什么的情况下尝试“修复它”是没有意义的。
好消息是,Mono 分析器 - 具有用于识别哪些内容引用了哪些内容的内置工具 - 非常有助于完成这项工作。
根据您的描述,我知道您已经找到了这个工具 - 但对于其他阅读者,请参阅 - http://docs.xamarin.com/ios/Guides/Deployment%252c_Testing%252c_and_Metrics/Monotouch_Profiler
一旦您确定了泄漏的原因和原因,那么第 3 步将需要一些思考,但希望很容易回答。
有时解决方案是:
WeakReference
类来避免泄漏的优点。无论发生什么,不要惊慌,从工程的角度来解决这个问题。这些泄漏也发生在非 MvvmCross 和非 MonoTouch 代码中 - 使用 MvvmCross 和干净的 IoC 架构应该更容易找到和删除它们。
如果问题确实出在某处的 MvvmCross 绑定中,请务必将其记录为错误 - 我非常重视这些问题!
MvvmCross repo 上关于我们是否不应该对所有绑定代码使用 WeakReferences 的长时间讨论中仍然存在一个未解决的错误 - 请参阅https://github.com/slodge/MvvmCross/issues/17 - 我已经考虑过这 - 它会帮助人们避免一些错误......但不是全部。这个问题仍然悬而未决。
更新:我没有回答
我们有很多自定义控件等,但是应该在哪里处理这些
框架应该为你处理这些。
如果没有,那可能是因为其他东西正在泄漏并保留在您的 View 上,而后者又保留在您的 Controls 上。您需要修复该潜在问题,而不是过早地调用控件上的 Dispose()。内存泄漏调试并不容易,但很有趣(有时)
一个好的规则是添加到基于 NSObject 的类的容器应该只引用使用 WeakReference 对象的容器。
像这样:
// MyView is a UIView, which is an NSObject, so the rule will apply here
class MyView : UIView {
WeakReference<UIViewController> myController;
public MyView (RectangleF bounds, UIViewController myContainer)
: base (bounds) {
this.myController = myContainer;
}
}