代码之家  ›  专栏  ›  技术社区  ›  JordiVilaplana

MvvmCross-在UISlider中处理绑定时获取TargetInvocationException和SIGABRT

  •  1
  • JordiVilaplana  · 技术社区  · 6 年前

    我正在和Xamarin一起做一个项目。iOS和MvvmCross(v5.6.3)以及我在一个视图控制器上有一个非常典型的UISlider,其值绑定到 float 属性。

    set.Bind(MySlider).For(x => x.Value).To(vm => vm.FloatProperty).TwoWay();
    

    当视图卸载并尝试处理现有绑定时(比如导航到另一个视图模型时),我会遇到以下未处理的异常 SIGABRT :

    Unhandled Exception:
    System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> UIKit.UIKitThreadAccessException: UIKit Consistency error: you are calling a UIKit method that can only be invoked from the UI thread.
      at UIKit.UIApplication.EnsureUIThread () [0x00023] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.9.1.24/src/Xamarin.iOS/UIKit/UIApplication.cs:88 
      at UIKit.UIControl.RemoveTarget (Foundation.NSObject target, System.IntPtr sel, UIKit.UIControlEvent events) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.9.1.24/src/Xamarin.iOS/UIKit/UIControl.g.cs:235 
      at UIKit.UIControl.RemoveTarget (System.EventHandler notification, UIKit.UIControlEvent events) [0x00057] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.9.1.24/src/Xamarin.iOS/UIKit/UIControl.cs:116 
      at UIKit.UIControl.remove_ValueChanged (System.EventHandler value) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.9.1.24/src/Xamarin.iOS/UIKit/UIControl.cs:209 
      at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke(System.Reflection.MonoMethod,object,object[],System.Exception&)
      at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00032] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.9.1.24/src/Xamarin.iOS/mcs/class/corlib/System.Reflection/MonoMethod.cs:305 
       --- End of inner exception stack trace ---
      at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00046] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.9.1.24/src/Xamarin.iOS/mcs/class/corlib/System.Reflection/MonoMethod.cs:313 
      at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.9.1.24/src/Xamarin.iOS/mcs/class/referencesource/mscorlib/system/reflection/methodbase.cs:229 
      at MvvmCross.Platform.WeakSubscription.MvxWeakEventSubscription`1[TSource].RemoveEventHandler () [0x00024] in <6adc0d5857264558a9d45778a78ae02a>:0 
      at MvvmCross.Platform.WeakSubscription.MvxWeakEventSubscription`1[TSource].Dispose (System.Boolean disposing) [0x00003] in <6adc0d5857264558a9d45778a78ae02a>:0 
      at MvvmCross.Platform.WeakSubscription.MvxWeakEventSubscription`1[TSource].Dispose () [0x00000] in <6adc0d5857264558a9d45778a78ae02a>:0 
      at MvvmCross.Binding.iOS.Target.MvxUISliderValueTargetBinding.Dispose (System.Boolean isDisposing) [0x0001b] in <614c9ef828c14ba687a40ec2656f480f>:0 
      at MvvmCross.Binding.Bindings.MvxBinding.Finalize () [0x00000] in <866b1e46764b48aab0d408952a6f006f>:0 
    2018-04-09 23:15:20.210 MyProject.iOS[73770:3302608] Unhandled managed exception:
    Exception has been thrown by the target of an invocation. (System.Reflection.TargetInvocationException)
      at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00046] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.9.1.24/src/Xamarin.iOS/mcs/class/corlib/System.Reflection/MonoMethod.cs:313 
      at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.9.1.24/src/Xamarin.iOS/mcs/class/referencesource/mscorlib/system/reflection/methodbase.cs:229 
      at MvvmCross.Platform.WeakSubscription.MvxWeakEventSubscription`1[TSource].RemoveEventHandler () [0x00024] in <6adc0d5857264558a9d45778a78ae02a>:0 
      at MvvmCross.Platform.WeakSubscription.MvxWeakEventSubscription`1[TSource].Dispose (System.Boolean disposing) [0x00003] in <6adc0d5857264558a9d45778a78ae02a>:0 
      at MvvmCross.Platform.WeakSubscription.MvxWeakEventSubscription`1[TSource].Dispose () [0x00000] in <6adc0d5857264558a9d45778a78ae02a>:0 
      at MvvmCross.Binding.iOS.Target.MvxUISliderValueTargetBinding.Dispose (System.Boolean isDisposing) [0x0001b] in <614c9ef828c14ba687a40ec2656f480f>:0 
      at MvvmCross.Binding.Bindings.MvxBinding.Finalize () [0x00000] in <866b1e46764b48aab0d408952a6f006f>:0 
     --- inner exception ---
    UIKit Consistency error: you are calling a UIKit method that can only be invoked from the UI thread. (UIKit.UIKitThreadAccessException)
      at UIKit.UIApplication.EnsureUIThread () [0x00023] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.9.1.24/src/Xamarin.iOS/UIKit/UIApplication.cs:88 
      at UIKit.UIControl.RemoveTarget (Foundation.NSObject target, System.IntPtr sel, UIKit.UIControlEvent events) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.9.1.24/src/Xamarin.iOS/UIKit/UIControl.g.cs:235 
      at UIKit.UIControl.RemoveTarget (System.EventHandler notification, UIKit.UIControlEvent events) [0x00057] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.9.1.24/src/Xamarin.iOS/UIKit/UIControl.cs:116 
      at UIKit.UIControl.remove_ValueChanged (System.EventHandler value) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.9.1.24/src/Xamarin.iOS/UIKit/UIControl.cs:209 
      at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke(System.Reflection.MonoMethod,object,object[],System.Exception&)
      at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00032] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.9.1.24/src/Xamarin.iOS/mcs/class/corlib/System.Reflection/MonoMethod.cs:305 
    2018-04-09 23:15:20.210 MyProject.iOS[73770:3302608] critical: Stacktrace:
    
    2018-04-09 23:15:20.211 MyProject.iOS[73770:3302608] critical: 
    Native stacktrace:
    
    2018-04-09 23:15:20.212 MyProject.iOS[73770:3302608] critical:  0   MyProject.iOS                       0x00000001038b4574 mono_handle_native_crash + 244
    2018-04-09 23:15:20.212 MyProject.iOS[73770:3302608] critical:  1   libsystem_platform.dylib            0x000000010bbecf5a _sigtramp + 26
    2018-04-09 23:15:20.213 MyProject.iOS[73770:3302608] critical:  2   ???                                 0x0000000103dd308a 0x0 + 4359794826
    2018-04-09 23:15:20.213 MyProject.iOS[73770:3302608] critical:  3   libsystem_c.dylib                   0x000000010b8820eb abort + 127
    2018-04-09 23:15:20.213 MyProject.iOS[73770:3302608] critical:  4   MyProject.iOS                       0x0000000103a5b2df xamarin_unhandled_exception_handler + 47
    2018-04-09 23:15:20.214 MyProject.iOS[73770:3302608] critical:  5   MyProject.iOS                       0x000000010391b854 mono_invoke_unhandled_exception_hook + 148
    2018-04-09 23:15:20.214 MyProject.iOS[73770:3302608] critical:  6   MyProject.iOS                       0x00000001039c2a3e mono_thread_internal_unhandled_exception + 110
    2018-04-09 23:15:20.215 MyProject.iOS[73770:3302608] critical:  7   MyProject.iOS                       0x000000010391d15a mono_gc_run_finalize + 842
    2018-04-09 23:15:20.215 MyProject.iOS[73770:3302608] critical:  8   MyProject.iOS                       0x00000001039fc9ba sgen_gc_invoke_finalizers + 234
    2018-04-09 23:15:20.215 MyProject.iOS[73770:3302608] critical:  9   MyProject.iOS                       0x000000010391eae4 finalizer_thread + 756
    2018-04-09 23:15:20.215 MyProject.iOS[73770:3302608] critical:  10  MyProject.iOS                       0x00000001039c3600 start_wrapper + 704
    2018-04-09 23:15:20.215 MyProject.iOS[73770:3302608] critical:  11  libsystem_pthread.dylib             0x000000010bbfe6c1 _pthread_body + 340
    2018-04-09 23:15:20.216 MyProject.iOS[73770:3302608] critical:  12  libsystem_pthread.dylib             0x000000010bbfe56d _pthread_body + 0
    2018-04-09 23:15:20.216 MyProject.iOS[73770:3302608] critical:  13  libsystem_pthread.dylib             0x000000010bbfdc5d thread_start + 13
    2018-04-09 23:15:20.216 MyProject.iOS[73770:3302608] critical: 
    =================================================================
    Got a SIGABRT while executing native code. This usually indicates
    a fatal error in the mono runtime or one of the native libraries 
    used by your application.
    =================================================================
    

    装订很好,只有在 我尝试导航到另一个视图模型 正在卸载视图

    我错过什么了吗?或者这可能是MvvmCross上的错误?

    编辑: 最后检查了在卸载视图时是否发生此问题,无论是否导航到其他视图模型。我已经删除了指向导航问题的引用。

    2 回复  |  直到 6 年前
        1
  •  3
  •   Plac3Hold3r    6 年前

    MvvmCross 5中当前存在一个错误。x、 x关于 UISlider 。此问题已通过修复 PR 2750 将在版本6.0.0中提供

    同时,您应该能够通过使用修复程序创建自定义绑定来覆盖该绑定,以便为您的项目修复它。问题在 Dispose

    public class FixedMvxUISliderValueTargetBinding : MvxPropertyInfoTargetBinding<UISlider>
    {
        private IDisposable _subscription;
    
        public FixedMvxUISliderValueTargetBinding(object target, PropertyInfo targetPropertyInfo) 
            : base(target, targetPropertyInfo) { }
    
        protected override void SetValueImpl(object target, object value)
        {
            var view = target as UISlider;
            if (view == null) return;
            view.Value = (float)value;
        }
    
        private void HandleSliderValueChanged(object sender, EventArgs e)
        {
            var view = View;
            if (view == null) return;
            FireValueChanged(view.Value);
        }
    
        public override MvxBindingMode DefaultMode => MvxBindingMode.TwoWay;
    
        public override void SubscribeToEvents()
        {
            var slider = View;
            if (slider == null)
            {
                MvxBindingTrace.Trace(
                    MvxTraceLevel.Error, 
                    "Error - UISlider is null in MvxUISliderValueTargetBinding");
                return;
            }
            _subscription = slider.WeakSubscribe(
                nameof(slider.ValueChanged), 
                HandleSliderValueChanged);
        }
    
        protected override void Dispose(bool isDisposing)
        {
            base.Dispose(isDisposing);
            if (isDisposing)
            {
                _subscription?.Dispose();
                _subscription = null;
            }
        }
    }
    

    然后在你的 Setup.cs 注册绑定。注意,请确保您致电 base.FillTargetFactories 第一

    protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
    {
        base.FillTargetFactories(registry);
        registry.RegisterPropertyInfoBindingFactory(
            typeof(FixedMvxUISliderValueTargetBinding),
            typeof(UISlider),
            nameof(UISlider.Value));
    }
    
        2
  •  1
  •   ColeX    6 年前

    您正在调用只能从UI线程调用的UIKit方法。

    尝试在UIThread中调用navigate方法。

    this.InvokeOnMainThread(async () =>
    {
        //navigate 
    });
    

    如果上述操作不起作用,可以尝试关闭UI线程检查。

    var previous = UIApplication.CheckForIllegalCrossThreadCalls;  
    UIApplication.CheckForIllegalCrossThreadCalls = false;  
    //navigate 
    UIApplication.CheckForIllegalCrossThreadCalls = previous;