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的内存泄漏?

Monotouch (Xamarin.iOS) 記憶體漏機

发生的情况是,存在跨越本机管理的边界的循环依赖项(使用事件处理程序(,当前 Xamarin.iOS 运行时/GC 无法检测到这一点。

您已经找到了此问题的解决方法:通过删除事件处理程序来中断循环依赖项。

这是一段详细解释情况的视频: http://xamarin.com/evolve/2013#session-0w86u7bco2