2012-04-02 21 views
1

便宜上、各ビューに変数/参照を必要とせずに待機インジケータを表示できるヘルパークラスを使用しています。クラスIはDFActivity指標を作成し、パラメータで指定されたビューに表示しています、この方法では、静的メソッド公共静的メソッドで初期化され、NSNotificationCenterを使用してオブジェクトが初期化されたメモリリーク

static void ShowActivityIndicator(UIView view, bool animated, UIActivityIndicatorViewStyle style) 

を実装:

DFActivityIndicator activityIndicator = new DFActivityIndicator(view.Bounds); 
view.AddSubview(activityIndicator); 
activityIndicator.LabelText = NSBundle.MainBundle.LocalizedString("Loading...", ""); 
activityIndicator.Indicator.ActivityIndicatorViewStyle = style; 
activityIndicator.Show(true); 

方法のコンストラクタは次のとおりです。

public DFActivityIndicator(RectangleF frame) : base(frame) 
{  

    Indicator = new UIActivityIndicatorView(UIActivityIndicatorViewStyle.Gray); 
    this.AddSubview(Indicator); 
    Indicator.StartAnimating(); 
    Indicator.Frame = new RectangleF(0.0f, 0.0f, 20.0f, 20.0f); 
    Indicator.StartAnimating(); 

    //... 

    Label = new UILabel(Bounds); 

    RotationTransform = CGAffineTransform.MakeIdentity(); 
    NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.DidChangeStatusBarOrientationNotification, DeviceOrientationDidChange, this); 

} 

ここで、インタフェースを回転させると、オブザーバはインジケータを回転させることができます。インジケータはもはや必要ないときは、私は他の静的メソッドがあります。これは正常に動作している

public static bool HideActivityIndicator(UIView view, bool animated) 
{ 
    UIView viewToRemove = null; 
    foreach(UIView v in view.Subviews) 
    { 
    if (v is DFActivityIndicator) 
    { 
     viewToRemove = v; 
    } 
    } 

    if (viewToRemove != null) 
    { 
    DFActivityIndicator activityIndicator = viewToRemove as DFActivityIndicator; 
    NSNotificationCenter.DefaultCenter.RemoveObserver(activityIndicator, UIApplication.DidChangeStatusBarOrientationNotification, null); 
    activityIndicator.RemoveFromSuperview(); 
    activityIndicator.Dispose(); 
    activityIndicator = null; 
    return true; 
    } 
    else 
    { 
    return false; 
    } 
} 

、モノプロファイラは、私がShowActivityIndicatorを呼び出していますたびに、各インスタンスがメモリに保持されていることを示し期待しても、Iすべてのインスタンスに対してHideActivityIndicatorと呼び出してください。私のアプリケーションのメモリは、クラッシュするまで増加しています(メモリリークのようです)。デバッグのために、オリエンテーションの変更でオブザーバを削除しようとしました: NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.DidChangeStatusBarOrientationNotification, DeviceOrientationDidChange, this)) と...コードがもう漏れていません。 MonoTouchのバグですか、それとも何か間違っていますか?

+0

私の推測では、私は右AddObserver/RemoveObserverメソッドを使用していないです。 – nicolas

+1

HideActivityIndi​​catorでオブザーバを削除しても機能しないと言っていますが、オリエンテーションを変更するとオブザーバを削除すると効果がありますか? HeapShotプロファイラは、「逆参照」チェックボックスをクリックすると、どのオブジェクトがDFActivityIndi​​catorを有効にしているかを示すこともできます。 –

+0

「AddObserver」と「RemoveObserver」という行にコメントしているときは、もうリークがないようです。 'DFActivityIndi​​cator'を生かし続けるようなリファレンスは、' System.Collection.Generic.List 'によって保持される' MonoTouch.Foundation.InternalNSNotificationHandler'によって保持される 'System.Action 'であり、 'MonoTouch .Foundation.NSNotificationCenter'。 – nicolas

答えて

3

はい、あなたはAddObserver/RemoveObserverメソッドを正しく使用していないと思います。ここで

はあなたが使用している過負荷でやっていることです。

NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.DidChangeStatusBarOrientationNotification, DeviceOrientationDidChange, this); 

あなたはこれらの通知はから来る場合DeviceOrientationChangeコールバック、をトリガーするステータスバーの向きの変更、の通知を受け取るために登録されていますthis。だからあなたのコールバックは決して起動されません(あなたのDFActivityIndi​​catorは決してそのような通知をポストしません)。しかし、デフォルトのセンター(またはより良い、あなたがコメントで言及した一連のオブジェクト)はビューへの参照を保持します。

NSNotificationCenter.DefaultCenter.RemoveObserver(activityIndicator, UIApplication.DidChangeStatusBarOrientationNotification, null); 

通知オブザーバではなくビューを削除しようとしています。残りのパラメータを説明する必要はありません。ここで

は、あなたが何をすべきかです:

//To add the observer: 
NSObject observerObject; 
//.. 
this.observerObject = NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.DidChangeStatusBarOrientationNotification, DeviceOrientationDidChange) 
//.. 
//To remove the observer: 
NSNotificationCenter.DefaultCenter.RemoveObserver(this.observerObject); 
+1

ありがとうございました!私の問題が修正されました! – nicolas

関連する問題