3

我遇到了一个奇怪的问题,导致 MonoTouch 内存泄漏。这是我的设置。

CaseTabController - UITabBarController
-- CaseMediaItemsController - UIViewController
-- CaseInfoController (irrelevant) - UIViewController

子控制器显示为选项卡。从子控制器,我正在尝试将一些NavigationItem(s)添加到 parent UITabBarController。但是,当我访问 时ParentViewController,会维护一个引用,使我的对象保持活动状态并且永远不会被垃圾收集。

仅将以下代码添加到子 UIViewControllerViewDidLoad会导致内存泄漏。

var ni = ParentViewController.NavigationItem;
ni = null;

可能父 UITabBarController 永远不会被处置,因为我的子标签引用它。这是 HeapShot 的输出。

ParentViewController可以从子选项卡访问

内存泄漏的 HeapShot

ParentViewController无法从子选项卡访问

没有内存泄漏的 HeapShot

请注意,除了步骤之外,每个内存快照都是在执行相同操作后拍摄的。注意没有引用 ParentViewController 的快照是如何减少实例的,因为它们正在被释放。它们被处理得如此之快,以至于我实际上是在查看有问题的控制器时拍摄了快照。没有访问 ParentViewController 的快照是在访问另一个控制器时拍摄的。在每种情况下,UITabBarController 都已从 UINavigationController 中弹出。

任何想法为什么 CaseMediaItemsController 在访问 ParentViewController 时维护对 CaseTabController 的引用?

4

1 回答 1

6

如需完整答案,请查看http://xamarin.com/evolve/2013#session-0w86u7bco2

基本上,通过在子项中引用父项,您就有了一个循环,并且将 NavigationItem 设置null为还不够,您还必须Dispose()这样做。但是您必须确保此时可以 Dispose () 对象。

var ni = ParentViewController.NavigationItem;
ni.Dispose ();
ni = null;

您也可以不保留对 NavigationItem 的强引用,如果您需要ni变量以方便起见,请将其设为WeakReference<UINavigationItem>. 这将允许它被垃圾收集。

WeakReference<UINavigationItem> ni;

public override void ViewDidLoad ()
{
    ni = new WeakReference<UINavigationItem> (ParentViewController.NavigationItem);

    //Nothing else here.
}

然后你可以ni像这样使用:

if (ni.Target != null)
    Console.WriteLine (ni.Target.Title);
于 2013-07-02T08:39:25.243 回答