2012-04-02 93 views
1

爲了方便,我使用了一個輔助類,它允許顯示等待指示符,而不需要在每個視圖中都有變量/引用。這個類實現公共靜態方法使用靜態方法初始化並使用NSNotificationCenter對象的內存泄漏

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

在這種方法中,我創建一個DFActivity指標和參數中給出的視圖中顯示它:

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時間,每個實例保存到內存中,即使我針對所有實例調用HideActivityIndicator。我的應用程序的內存正在增加,直到崩潰(似乎是內存泄漏)。對於調試,我試圖刪除方向變化的觀察者: NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.DidChangeStatusBarOrientationNotification, DeviceOrientationDidChange, this)) ...代碼不再泄漏。這是一個MonoTouch錯誤還是我正在做其他錯誤?

+0

我的猜測是,我沒有使用正確的addObserver/RemoveObserver方法。 – nicolas 2012-04-02 17:07:23

+1

所以你說在HideActivityIndi​​cator中刪除觀察者不起作用,但是在方向變化時刪除觀察者會起作用嗎? HeapShot分析器還能夠告訴你,如果您單擊「Inverse References」複選框,哪個對象將使DFActivityIndi​​cator保持活動狀態。 – 2012-04-02 17:15:37

+0

沒有,當我評論'AddObserver'和'RemoveObserver'行時,似乎沒有泄漏了。似乎保持'DFActivityIndi​​cator'活動的引用是'System.Action ',由'MonoTouch.Foundation.InternalNSNotificationHandler'保存,'System.Collection.Generic.List '由'MonoTouch保存.Foundation.NSNotificationCenter'。 – nicolas 2012-04-02 17:23:40

回答

3

是的,我認爲你沒有正確使用AddObsever/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 2012-04-03 06:33:26