halkar / xamarin-range-slider

Range slider for Xamarin and Xamarin.Forms
https://www.nuget.org/packages/Xamarin.Forms.RangeSlider/
MIT License
89 stars 51 forks source link

iOS: NSInternalInconsistencyException when navigating back from ListView #104

Closed Jesuszilla closed 6 years ago

Jesuszilla commented 7 years ago

I have a ViewCell that contains a slider in a shared project as follows:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Xamarin.RangeSlider.Forms;

namespace MyApp
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class SliderViewCell : ViewCell
    {
        public static readonly BindableProperty LabelProperty =
            BindableProperty.Create("Label", typeof(string), typeof(SliderViewCell), "");

        public string Label
        {
            get { return (string)GetValue(LabelProperty); }
            set { SetValue(LabelProperty, value); }
        }

        public static readonly BindableProperty LowerValueProperty =
            BindableProperty.Create("LowerValue", typeof(float), typeof(SliderViewCell), 0.0F, BindingMode.TwoWay);

        public float LowerValue
        {
            get { return (float)GetValue(LowerValueProperty); }
            set { SetValue(LowerValueProperty, value); }
        }

        public static readonly BindableProperty UpperValueProperty =
            BindableProperty.Create("UpperValue", typeof(float), typeof(SliderViewCell), 100.0F, BindingMode.TwoWay);

        public float UpperValue
        {
            get { return (float)GetValue(UpperValueProperty); }
            set { SetValue(UpperValueProperty, value); }
        }

        public static readonly BindableProperty MinimumValueProperty =
            BindableProperty.Create("MinimumValue", typeof(float), typeof(SliderViewCell), Single.MinValue);

        public float MinimumValue
        {
            get { return (float)GetValue(MinimumValueProperty); }
            set { SetValue(MinimumValueProperty, value); }
        }

        public static readonly BindableProperty MaximumValueProperty =
            BindableProperty.Create("MaximumValue", typeof(float), typeof(SliderViewCell), Single.MaxValue);

        public float MaximumValue
        {
            get { return (float)GetValue(MaximumValueProperty); }
            set { SetValue(MaximumValueProperty, value); }
        }

        public static readonly BindableProperty IsOneThumbProperty =
            BindableProperty.Create("IsOneThumb", typeof(bool), typeof(SliderViewCell), true);

        public bool IsOneThumb
        {
            get { return (bool)GetValue(IsOneThumbProperty); }
            set { SetValue(IsOneThumbProperty, value); }
        }

        //public static readonly BindableProperty SliderWidthRequestProperty =
        //    BindableProperty.Create("SliderWidthRequest", typeof(double), typeof(SliderViewCell), -1.0);

        //public double SliderWidthRequest
        //{
        //    get { return (double)GetValue(SliderWidthRequestProperty); }
        //    set { SetValue(SliderWidthRequestProperty, value); }
        //}

        public static readonly BindableProperty FormatLabelProperty =
            BindableProperty.Create("FormatLabel", typeof(Func<Xamarin.RangeSlider.Common.Thumb, float, string>), typeof(SliderViewCell), null);

        public Func<Xamarin.RangeSlider.Common.Thumb, float, string> FormatLabel
        {
            get { return (Func<Xamarin.RangeSlider.Common.Thumb, float, string>)GetValue(FormatLabelProperty); }
            set { SetValue(FormatLabelProperty, value); }
        }

        public static readonly BindableProperty ShowThumbTextProperty =
            BindableProperty.Create("ShowThumbText", typeof(bool), typeof(SliderViewCell), true);

        public bool ShowThumbText
        {
            get { return (bool)GetValue(ShowThumbTextProperty); }
            set { SetValue(ShowThumbTextProperty, value); }
        }

        public static readonly BindableProperty TextFormatProperty =
            BindableProperty.Create("TextFormat", typeof(string), typeof(SliderViewCell), "");

        public string TextFormat
        {
            get { return (string)GetValue(TextFormatProperty); }
            set { SetValue(TextFormatProperty, value); }
        }

        public SliderViewCell ()
        {
            InitializeComponent();

            this.slider.SetBinding(RangeSlider.FormatLabelProperty, "FormatLabel", BindingMode.OneWay);
            this.slider.SetBinding(RangeSlider.TextFormatProperty, "TextFormat", BindingMode.OneWay);
            this.slider.SetBinding(RangeSlider.ShowTextAboveThumbsProperty, "ShowThumbText", BindingMode.OneWay);
            this.slider.SetBinding(RangeSlider.LowerValueProperty, "LowerValue", BindingMode.TwoWay);
            this.slider.SetBinding(RangeSlider.UpperValueProperty, "UpperValue", BindingMode.TwoWay);
            this.slider.SetBinding(RangeSlider.MinimumValueProperty, "MinimumValue", BindingMode.OneWay);
            this.slider.SetBinding(RangeSlider.MaximumValueProperty, "MaximumValue", BindingMode.OneWay);
            this.slider.SetBinding(RangeSlider.MinThumbHiddenProperty, "IsOneThumb", BindingMode.OneWay);
            //this.slider.SetBinding(RangeSlider.WidthRequestProperty, "SliderWidthRequest", BindingMode.OneWay);
        }

        public void Deinitialize()
        {
            this.slider.RemoveBinding(RangeSlider.FormatLabelProperty);
            this.slider.RemoveBinding(RangeSlider.TextFormatProperty);
            this.slider.RemoveBinding(RangeSlider.ShowTextAboveThumbsProperty);
            this.slider.RemoveBinding(RangeSlider.LowerValueProperty);
            this.slider.RemoveBinding(RangeSlider.UpperValueProperty);
            this.slider.RemoveBinding(RangeSlider.MinimumValueProperty);
            this.slider.RemoveBinding(RangeSlider.MaximumValueProperty);
            this.slider.RemoveBinding(RangeSlider.MinThumbHiddenProperty);
            this.slider = null;
        }
    }
}

When navigating backwards from this ViewCell using the back button on the navigation bar, I get the following exception:

Objective-C exception thrown.  Name: NSInternalInconsistencyException Reason: An instance 0x17c9ec10 of class UIImageView was deallocated while key value observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x16590400> (
<NSKeyValueObservance 0x17ca11e0: Observer: 0x17c9b5b0, Key path: frame, Options: <New: YES, Old: NO, Prior: NO> Context: 0x0, Property: 0x17ca1210>
)
Native stack trace:
    0   CoreFoundation                      0x25a3f933 <redacted> + 150
    1   libobjc.A.dylib                     0x251dae17 objc_exception_throw + 38
    2   CoreFoundation                      0x25a3f861 <redacted> + 0
    3   Foundation                          0x261f67a9 <redacted> + 408
    4   CoreFoundation                      0x25956d99 <redacted> + 148
    5   libobjc.A.dylib                     0x251f4f67 <redacted> + 150
    6   libobjc.A.dylib                     0x251f53a9 <redacted> + 388
    7   CoreFoundation                      0x2594ef89 _CFAutoreleasePoolPop + 16
    8   Foundation                          0x262697a1 <redacted> + 580
    9   CoreFoundation                      0x25a01dff <redacted> + 14
    10  CoreFoundation                      0x25a019ed <redacted> + 452
    11  CoreFoundation                      0x259ffd5b <redacted> + 794
    12  CoreFoundation                      0x2594f229 CFRunLoopRunSpecific + 520
    13  CoreFoundation                      0x2594f015 CFRunLoopRunInMode + 108
    14  GraphicsServices                    0x26f3fac9 GSEventRunModal + 160
    15  UIKit                               0x2a023189 UIApplicationMain + 144
    16  MyApp.iOS              0x00f54870 MyApp.iOS + 15014000
    17  MyApp.iOS              0x00ed9b04
Objective-C exception thrown.  Name: NSInternalInconsistencyException Reason: An instance 0x17c9ec10 of class UIImageView was deallocated while key value observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x16590400> (
<NSKeyValueObservance 0x17ca11e0: Observer: 0x17c9b5b0, Key path: frame, Options: <New: YES, Old: NO, Prior: NO> Context: 0x0, Property: 0x17ca1210>
)
Native stack trace:
    0   CoreFoundation                      0x25a3f933 <redacted> + 150
    1   libobjc.A.dylib                     0x251dae17 objc_exception_throw + 38
    2   CoreFoundation                      0x25a3f861 <redacted> + 0
    3   Foundation                          0x261f67a9 <redacted> + 408
    4   CoreFoundation                      0x25956d99 <redacted> + 148
    5   libobjc.A.dylib                     0x251f4f67 <redacted> + 150
    6   libobjc.A.dylib                     0x251f53a9 <redacted> + 388
    7   CoreFoundation                      0x2594ef89 _CFAutoreleasePoolPop + 16
    8   Foundation                          0x262697a1 <redacted> + 580
    9   CoreFoundation                      0x25a01dff <redacted> + 14
    10  CoreFoundation                      0x25a019ed <redacted> + 452
    11  CoreFoundation                      0x259ffd5b <redacted> + 794
    12  CoreFoundation                      0x2594f229 CFRunLoopRunSpecific + 520
    13  CoreFoundation                      0x2594f015 CFRunLoopRunInMode + 108
    14  GraphicsServices                    0x26f3fac9 GSEventRunModal + 160
    15  UIKit                               0x2a023189 UIApplicationMain + 144
    16  MyApp.iOS              0x00f54870 MyApp.iOS + 15014000
    17  MyApp.iOS              0x00ed9b04

I tried solving this using the Deinitialize method I wrote though it didn't work, so this points to some problem within the iOS code for the Xamarin.Forms.RangeSlider itself. This is on version 0.7.13, Xamarin.Forms version 2.4.0.18342.

halkar commented 7 years ago

@Jesuszilla I can't reproduce the problem, can you provide sample project?

kubito commented 6 years ago

@halkar Hello, I have same problem.

It is caused by unregistered Observers. What are observers here for? I see no reason.

halkar commented 6 years ago

Thanks, @kubito TBH, I don't remember why it is there and I've been thinking about removing it for a while. Will do soon-ish.

kubito commented 6 years ago

@halkar I’m using your code without Observers without any known issue.

halkar commented 6 years ago

Should be fixed in 0.7.16

kubito commented 6 years ago

@halkar tested - OK, thanks.