MonoTouch对象引用阻止垃圾回收

3

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

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

子控制器以选项卡形式显示。我想从子控制器中向父UITabBarController添加一些NavigationItem。然而,当我访问ParentViewController时,引用被维护,使我的对象保持活动状态,永远不会被垃圾回收。仅仅将以下代码添加到子UIViewController的ViewDidLoad中就会导致内存泄漏。
var ni = ParentViewController.NavigationItem;
ni = null;

我的父级UITabBarController可能永远不会被处理,因为我的子选项卡引用了它。以下是HeapShot的输出。
有从子标签访问ParentViewController: HeapShot with memory leak 没有从子标签访问ParentViewController: HeapShot without memory leak 请注意,在执行相同的操作后拍摄了每个内存快照。请注意,没有对ParentViewController的引用的快照实例更少,因为它们正在被处理。它们被处理得非常快,事实上我在查看相关控制器时拍摄了快照。没有访问ParentViewController的快照是在访问另一个控制器时拍摄的。在每种情况下,UITabBarController已经从UINavigationController中弹出。
有任何想法,为什么CaseMediaItemsController在访问ParentViewController时保持对CaseTabController的引用?
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);

太棒了!不过我有一个后续问题,我会为此创建另一个SO问题。我在MonoTouch绑定中遇到了类似的问题。使用弱委托(NSObject),我将控制器用作子对象的委托。这也创建了一个循环引用,防止收集。我必须在“ViewPoppedFromNavigationController”上将弱委托设置为null。那么在monotouch绑定中使用WeakReference,特别是模型和委托,怎么样? - Paul Knopf
你是否正确使用WrapAttribute?http://docs.xamarin.com/guides/ios/advanced_topics/binding_objective-c_libraries#Binding_Protocols - Stephane Delcroix
我有这个。我唯一缺少的是ArgumentSemantic.Assign。那会引起这个问题吗? - Paul Knopf
我终于开始实现它了,但是它不起作用。首先,没有通用的WeakReference。此外,原始问题仍然存在。"_parentNavigationItem = new WeakReference (ParentViewController);" 有什么想法吗? - Paul Knopf
有一个通用的WeakReference。 - Stephane Delcroix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接