我有一个奇怪的问题,导致MonoTouch内存泄漏。这是我的设置。
CaseTabController - UITabBarController
-- CaseMediaItemsController - UIViewController
-- CaseInfoController (irrelevant) - UIViewController
子控制器显示为选项卡。从子控制器,我试图将一些NavigationItem
(s)添加到父UITabBarController
。但是,当我访问ParentViewController
时,会保留一个引用,使我的对象保持活动状态并且永远不会被垃圾回收。
仅将以下代码添加到子UIViewController的ViewDidLoad
会导致内存泄漏。
var ni = ParentViewController.NavigationItem;
ni = null;
可能父UITabBarController从未被处理掉,因为我的子标签引用了它。这是HeapShot的输出。
访问ParentViewController
来自儿童标签
无法访问儿童标签ParentViewController
请注意,除了步骤之外,每个内存快照都在执行相同的操作。请注意快照WITHOUT引用ParentViewController的实例如何更少,因为正在处理它们。它们处理得如此之快,以至于我在查看相关控制器时实际拍摄了快照。没有访问ParentViewController的快照正在访问另一个控制器。在每种情况下,UITabBarController都已从UINavigationController中弹出。
为什么CaseMediaItemsController在访问ParentViewController时维护对CaseTabController的引用的任何想法?
答案 0 :(得分: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);