2012-04-02 4 views
1

편의상 각 뷰에 변수/참조가 필요없이 대기 표시기를 표시 할 수있는 도우미 클래스를 사용하고 있습니다. 클래스는이 방법, 나는 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

HideActivityIndicator에서 옵저버를 제거해도 효과가 없지만 방향 변경시 옵저버를 제거하면 효과가 있다는 말입니까? HeapShot 프로파일 러는 "역 참조"확인란을 클릭하면 어떤 객체가 DFActivityIndicator를 활성 상태로 유지하고 있는지를 알 수 있습니다. –

+0

'AddObserver'및 'RemoveObserver'행에 주석을 달 때 아니요, 더 이상 누수가없는 것으로 보입니다. 'DFActivityIndicator'가 살아있는 것처럼 보이는 레퍼런스는'System.Collection.Generic.List '에 의해 유지되는'MonoTouch.Foundation.InternalNSNotificationHandler'에 의해 유지되는'System.Action '이며,'MonoTouch .Founation.NSNotificationCenter'. – nicolas

답변

3

예, 사용자가 AddObserver/RemoveObserver 메서드를 올바르게 사용하지 않는 것 같습니다. 이러한 알림이에서 오는 경우, 을 DeviceOrientationChange 콜백을 트리거

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

당신은 상태 표시 줄의 방향 변경에 대한 알림을 수신하기 위해 등록하는, 다음은

당신이 오버로드를 사용하고 함께하고있는 것입니다 this. 따라서 DFActivityIndicator에서 알림을 게시하지 않으므로 콜백이 실행되지 않지만 기본 센터 (또는 더 나은 댓글에서 언급 한 일련의 객체)가보기에 대한 참조를 보유합니다.

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