我们正在实施一个似乎存在大量内存泄漏的应用程序。例如,我们有一个带有对应视图模型的视图,该视图在mono分析器中注册了38次,但应该对其进行垃圾回收。我们有很多自定义控件等,但是应该将它们放置在哪里-从ios 6开始,不再调用viewdidunload,所以我们应该在哪里进行清理?

问候

最佳答案

这是一个很大的问题...在一般情况下无法轻松回答。

通常,如果您编写漂亮的简单ViewModel和漂亮的简单View,那么您将不会遇到任何内存泄漏。

但是,如果您具有引用ViewModel的View,而这些View又具有以某种方式引用View的回调,那么很可能会发生内存泄漏-特别是如果您的视图模型订阅了服务上的事件。



一个特别讨厌的情况是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-几次-这不是入门级的解释,但最终还是有道理的!



所以,为了解决您当前的问题...


找出泄漏的是什么
找出原因-保留引用的是什么。
修理它。


关键是投入大量精力进行1和2的学习,然后再研究3的错误修复方法。在不真正了解“修复”的情况下尝试“修复”是没有意义的。

好消息是,Mono探查器及其内置工具可以识别对哪些内容的引用,对于帮助完成这项工作确实非常有用。

根据您的描述,我知道您已经找到了此工具-但是对于其他阅读者,请参见-http://docs.xamarin.com/ios/Guides/Deployment%252c_Testing%252c_and_Metrics/Monotouch_Profiler



一旦确定了泄漏的原因以及原因,那么第3步将需要一些思考,但希望可以轻松回答。

有时解决方案是:


只需修复一条糟糕的代码行...哪一行很难。
使用“后退”检测,可以确定何时断开绑定或事件。
使用“ willappear”,“ willdisappear”添加生命周期事件以更改您订阅/取消订阅事件的方式
使用除C#事件以外的其他方法-例如使用TinyMessenger之类的Messenger(或MvvmCross插件Messenger)-这些优点是它们通常使用WeakReference类来避免泄漏。
在“适当的时间”处理“某物”-再次计算“某物”和“适当的时间”是这方面的难点


无论发生什么情况,都不要惊慌,并且一定要从工程学角度解决这个问题。这些泄漏也会发生在非MvvmCross和非MonoTouch代码中-并且将MvvmCross与良好的干净IoC架构一起使用应该使它们更易于查找和删除。



如果问题确实出在某个地方的MvvmCross绑定中,则请将该日志记录为错误-我非常重视这些问题!

关于MvvmCross回购的漫长讨论中仍然存在一个开放的错误,即我们是否不应该对所有绑定代码使用WeakReferences-请参阅https://github.com/slodge/MvvmCross/issues/17-我已经考虑过这样做-它可以帮助人们避免某些错误...但不是所有的。这个问题仍然悬而未决。



更新:我没有回答


我们有很多自定义控件等,但是这些应该放在哪里


框架应为您处理这些。

如果不是,那可能是因为其他内容泄漏并保留了View,然后又保留了Control。您需要解决该潜在问题,而不是过早在Controls上调用Dispose()。内存泄漏调试并非易事,但有时很有趣。

关于memory-management - 何时以单点触控/mvvmcross释放对象,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14688044/

10-14 17:44