Monotouch (Xamarin.iOS) 記憶體漏機
本文关键字:Xamarin iOS Monotouch | 更新日期: 2023-09-27 18:34:50
我有一个具有复杂视图层次结构的应用程序,其中一个视图控制器(我们称之为RootVC(可以导致许多其他视图控制器。当我弹出RootVC时,我想完全释放它。我没有将引用存储在字段或其他地方,并相信这就足够了。但是最近我检查了Xamarin的堆镜头,并在"所有对象"部分看到许多RootVC实例保留在内存中。
例如:
sealed class VC1 : UIViewController
{
...
private void OpenVC2()
{
var vc2 = new VC2();
NavigationController.PushViewController(vc2, true);
}
}
sealed class VC2 : UIViewController
{
private UIButton button;
public override ViewDidLoad()
{
...
button = new UIButton(frame);
button.TouchUpInside += HandleButtonTouch;
...
}
private void HandleButtonTouch(object sender, EventArgs e)
{
NavigationController.PopViewControllerAnimated(true):
}
}
这是堆镜头截图的链接(由于声誉低,无法将它们作为图像发布( - https://i.stack.imgur.com/jMjiY.jpg
当我在VC2上时,我看到类似于第一个屏幕截图的内容。
当我弹出VC2并在VC1上时,堆镜头看起来像第二张图像。
出现一些VC2后,它看起来像第三个屏幕截图。
它们永远不会被处置或最终确定,它们会一直保留到最后。即使通过根也无法到达它们。这是不可接受的,因为内存有限,并且所有这些VC2都在内存中,我们可以轻松获得内存警告或应用程序终止。
但是,如果我订阅/取消订阅 View 上的按钮事件出现/消失,如下所示:
sealed class VC2 : UIViewController
{
private UIButton button;
public override ViewDidLoad()
{
...
button = new UIButton(frame);
...
}
public override void ViewWillAppear(bool animated)
{
...
button.TouchUpInside += HandleButtonTouch;
}
public override void ViewDidDisappear(bool animated)
{
...
button.TouchUpInside -= HandleButtonTouch;
}
private void HandleButtonTouch(object sender, EventArgs e)
{
NavigationController.PopViewControllerAnimated(true):
}
}
在这种情况下,VC2(及其所有视图等(在消失时会得到正确处理。 ~VC2(( 被调用,所有 VC2 在堆镜头中不再可见。
所以,问题来了。我做错了什么?我应该订阅/取消订阅上述控制事件吗?还是Xamarin.iOS的内存泄漏?
发生的情况是,存在跨越本机管理的边界的循环依赖项(使用事件处理程序(,当前 Xamarin.iOS 运行时/GC 无法检测到这一点。
您已经找到了此问题的解决方法:通过删除事件处理程序来中断循环依赖项。
这是一段详细解释情况的视频: http://xamarin.com/evolve/2013#session-0w86u7bco2