我有一个具有复杂视图层次结构的应用程序,其中一个视图控制器(我们称之为 RootVC)可以导致许多其他视图控制器。当我弹出 RootVC 时,我想完全释放它。我没有将引用存储在字段或其他地方,并且相信它就足够了。但最近我检查了 Xamarin 的 Heap Shot 并在“所有对象”部分看到许多 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):
}
}
这是 Heap Shot 截图的链接(由于声誉低,不能将它们作为图片发布)- http://imgur.com/a/3MYBr#1
当我在 VC2 上时,我看到类似于第一个屏幕截图的内容。
当我弹出 VC2 和 VC1 时,Heap Shot 看起来像第二张图像。
在出现几个 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 不再在 Heap Shot 中可见。
所以,这就是问题所在。我做错了什么?我应该订阅/取消订阅上述控制事件吗?还是 Xamarin.iOS 的内存泄漏?