Forum Xamarin.iOS

AddObserver and Dispose problem

I would like to observe an AVPlayerItem instance, but when I am trying to dispose the observer an exception is thrown:

Objective-C exception thrown. Name: NSRangeException Reason: Cannot remove an observer <__XamarinObjectObserver 0x1cb7ad90> for the key path "error" from <__XamarinObjectObserver 0x1cb7ad90> because it is not registered as an observer.

Code:

        this.sound = AVPlayerItem.FromUrl(url);
        this.soundErrorObserver = this.sound.AddObserver("error", NSKeyValueObservingOptions.New, this.OnErrorDetected);

        [...]

        this.soundErrorObserver.Dispose();
        this.soundErrorObserver = null;
        this.sound.Dispose();
        this.sound = null;

Am I doing something wrong?

Best Answer

Answers

  • rmaciasrmacias USBeta, University ✭✭✭✭✭

    To dispose of an observer, you don't call Dispose(), you'll need to remove it as an observer. It should be something like this:

    this.sound.RemoveObserver(this.soundErrorObserver, "error");

  • ZoldikeZoldike HUMember

    It's a new method in the Unified API. The documentation states that Dispose is the right way to remove that kind of observer.

    http://iosapi.xamarin.com/monodoc.ashx?link=M:Foundation.NSObject.AddObserver(System.String,Foundation.NSKeyValueObservingOptions,System.Action{Foundation.NSObservedChange})

  • rmaciasrmacias USBeta, University ✭✭✭✭✭

    Regardless, it looks like internally, the Dispose() method has a bug, as it's calling RemoveObserver on the wrong object. If you manually call RemoveObserver on the correct object, it should work. I'm not sure if it's new functionality or not, but it looks like calling Dispose() is calling RemoveObserver() internally, which is the correct way to to do it. It just looks like it's doing it wrong, per Adam's bug report.

  • adamkempadamkemp USInsider, Developer Group Leader mod

    The workaround is to use the lower-level API that is used internally by this function:

    sound.AddObserver(this, "error", NSKeyValueObservingOptions.New, Handle);
    
    // Later
    sound.RemoveObserver(this, "error", Handle);
    

    And then implement this method:

    public override void ObserveValue(NSString keyPath, NSObject ofObject, NSDictionary change, IntPtr context)
    {
        if (keyPath == "error" && context == Handle)
        {
            this.OnErrorDetected();
        }
        else
        {
            base.ObserveValue(keyPath, ofObject, change, context);
        }
    }
    
  • adamkempadamkemp USInsider, Developer Group Leader mod
    edited February 2015

    Using Ruben's suggestion you would use the same API, but instead of calling Dispose you would do this:

    sound.RemoveObserver(soundErrorObserver, "error", soundErrorObserver.Handle);
    

    But you still shouldn't call Dispose, and you will get a debug output saying you didn't call Dispose. This seems like a hackier solution than using the lower level API, but it is a bit easier.

  • ZoldikeZoldike HUMember

    Thanks guys, I wasn't sure if that's a bug.

  • OnurHazarOnurHazar USUniversity ✭✭✭
    edited October 2019

    They claimed that they resolved the issue: https://xamarin.github.io/bugzilla-archives/27/27220/bug.html but this doesn't seem to be fixed at all. It's still happening. While using dispose method to remove the observer, my app crashes with the same crash reason given. I will do the workaround which you guys mentioned. Thanks!

    Visual Studio Community 2019 for Mac
    Version 8.3.4 (build 8)
    Installation UUID: ae629ef6-b815-413a-a678-3fb356d9980b
    GTK+ 2.24.23 (Raleigh theme)
    Xamarin.Mac 5.16.1.24 (d16-3 / 08809f5b)

    Package version: 604000208
    

    Mono Framework MDK
    Runtime:
    Mono 6.4.0.208 (2019-06/07c23f2ca43) (64-bit)
    Package version: 604000208

    Xamarin.iOS
    Version: 13.4.0.2 (Visual Studio Community)
    Hash: e37549bc
    Branch: xcode11.1
    Build date: 2019-10-07 22:43:23-0400

    Operating System
    Mac OS X 10.14.6

  • tomas_svestkatomas_svestka Member ✭✭

    Agreed, definitely not fixed, the issue is present exactly on the latest Xamarin build to date as described in this topic (in 2015...)

Sign In or Register to comment.