François
François

Reputation: 3274

Xamarin Forms - iOS Custom Renderer - Disposing of observers

The following crashes when the page contening the ListView being customized disapears. The errors says my observers are not disposed of.

public class ChatListViewRenderer : ListViewRenderer
{
    private IDisposable _onContentSizeChangedObserver;
    private IDisposable _onFrameChangedObserver;

    protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
    {
        base.OnElementChanged(e);
        if (Control == null) return;

         _onContentSizeChangedObserver = Control.AddObserver(new NSString("contentSize"), NSKeyValueObservingOptions.OldNew, OnContentSizeChanged);
        _onFrameChangedObserver = Control.AddObserver(new NSString("frame"), NSKeyValueObservingOptions.OldNew, OnFrameChanged);
    }


    protected override void Dispose(bool disposing)
    {
        _onContentSizeChangedObserver.Dispose();
        _onFrameChangedObserver.Dispose();
        base.Dispose(disposing);
    }
}

UPDATE

I tried within ViewWillDisapear of the PageRenderer of the page containing the ListView but the issue remains.

public override void ViewWillDisappear(bool animated)
    {
        base.ViewWillDisappear(animated);

        var listRenderer = Platform.CreateRenderer(((MessagesPage)Element).MessagesList) as ChatListViewRenderer;
        listRenderer._onContentSizeChangedObserver.Dispose();
        listRenderer._onFrameChangedObserver.Dispose();
    }

Upvotes: 1

Views: 2106

Answers (2)

Nick Kovalsky
Nick Kovalsky

Reputation: 6462

A more "visual" example:

private IDisposable _onAppOrientationChangedObserver;

protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
   base.OnElementChanged (e);

   if (e.OldElement != null)
   {
      _onAppOrientationChangedObserver?.Dispose();
   }

   if (e.NewElement != null) 
   {
      if (Control!=null)
      {
            _onAppOrientationChangedObserver = NSNotificationCenter.DefaultCenter.AddObserver(UIDevice.OrientationDidChangeNotification, (obj) =>
            {
              _uiOrientation = UIApplication.SharedApplication.StatusBarOrientation;
              _deviceOrientation = UIDevice.CurrentDevice.Orientation;
            });
      }
   }

}

Upvotes: 0

Yuri S
Yuri S

Reputation: 5370

OnElementChanged is called twice - when control is created and then when disposed.

if(e.NewElement != null)
      addobserver and do other stuff
if(e.oldElement!=null)
       remove observer and destroy everything you allocated

Upvotes: 3

Related Questions