3

MonoTouch でメモリ リークが発生する奇妙な問題が発生しています。これが私のセットアップです。

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

子コントローラーはタブとして表示されます。NavigationItem子コントローラから、いくつかを親に追加しようとしていUITabBarControllerます。ただし、にアクセスするParentViewControllerと、参照が維持され、オブジェクトが生きたままになり、ガベージ コレクションが行われることはありません。

次のコードを子 UIViewController に追加するだけでViewDidLoad、メモリ リークが発生します。

var ni = ParentViewController.NavigationItem;
ni = null;

子タブが参照しているため、親の UITabBarController が破棄されることはありません。HeapShot からの出力は次のとおりです。

ParentViewController子タブからアクセス可能

メモリ リークのある HeapShot

子タブからのアクセスParentViewControllerなし

メモリリークのない HeapShot

各メモリ スナップショットは、手順を除いて同じことを行った後に取得していたことに注意してください。ParentViewController への参照なしのスナップショットが破棄されているため、インスタンスの数が少ないことに注意してください。それらは非常に迅速に破棄されているため、問題のコントローラーを表示しているときに実際にスナップショットを撮りました。別のコントローラーにアクセスしているときに、ParentViewController へのアクセスなしのスナップショットが取得されていました。いずれの場合も、UITabBarController は UINavigationController からポップされています。

ParentViewController にアクセスするときに CaseMediaItemsController が 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 に答える