MvvmCross:销毁UISlider绑定时出现TargetInvocationException与SIGABRT
我之前在MvvmCross 5.x版本的iOS项目里遇到过几乎一样的问题,结合对这个版本绑定机制的了解,给你几个可行的解决方案:
问题根源分析
这个SIGABRT异常包装的TargetInvocationException,大概率是因为MvvmCross 5.6.3的默认UISlider双向绑定在视图销毁阶段,存在绑定上下文释放与Slider事件回调的时序冲突:当视图卸载时,绑定上下文已经被清理,但Slider的ValueChanged事件可能仍持有绑定相关的引用,触发反射调用时找不到目标对象,最终引发崩溃。
解决方案1:手动提前解除Slider绑定
在视图控制器的ViewWillDisappear方法中,主动解除Slider的绑定,避免MvvmCross自动销毁绑定时出现冲突:
public override void ViewWillDisappear(bool animated) { base.ViewWillDisappear(animated); // 提前解除Slider的绑定,避免后续自动销毁时的异常 if (MySlider != null) { this.BindingContext.Unbind(MySlider); } }
如果需要一次性清理所有绑定,也可以直接调用:
this.BindingContext.ClearAllBindings();
解决方案2:使用自定义绑定替代默认绑定
MvvmCross的默认绑定依赖反射处理属性,在销毁阶段容易出现引用问题。我们可以自定义一个UISlider绑定,直接处理事件,减少反射依赖:
1. 实现自定义绑定类
public class CustomSliderValueBinding : MvxTargetBinding { private readonly UISlider _slider; private bool _isSubscribed; public CustomSliderValueBinding(UISlider slider) : base(slider) { _slider = slider; } public override Type TargetType => typeof(float); public override MvxBindingMode DefaultMode => MvxBindingMode.TwoWay; protected override void SetValueImpl(object target, object value) { if (target is UISlider slider && value is float floatValue) { slider.Value = floatValue; } } public override void SubscribeToEvents() { if (!_isSubscribed) { _slider.ValueChanged += OnSliderValueChanged; _isSubscribed = true; } } private void OnSliderValueChanged(object sender, EventArgs e) { if (sender is UISlider slider) { FireValueChanged(slider.Value); } } protected override void Dispose(bool isDisposing) { if (isDisposing && _isSubscribed) { _slider.ValueChanged -= OnSliderValueChanged; _isSubscribed = false; } base.Dispose(isDisposing); } }
2. 在Setup中注册自定义绑定
在项目的Setup.cs中,添加自定义绑定的注册:
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry) { base.FillTargetFactories(registry); // 注册自定义Slider绑定 registry.RegisterCustomBindingFactory<UISlider>("CustomValue", slider => new CustomSliderValueBinding(slider)); }
3. 替换原绑定代码
把原来的绑定代码替换为使用自定义绑定:
set.Bind(MySlider).For("CustomValue").To(vm => vm.FloatProperty).TwoWay();
解决方案3:升级MvvmCross版本(优先推荐,如果项目允许)
MvvmCross 5.6.3是2018年的旧版本,后续的v6.x及更高版本已经修复了大量绑定内存管理和销毁相关的bug。如果项目没有强依赖旧版本的特性,建议升级到稳定的新版本,从根源上解决这类问题。
额外检查点
- 确认你的视图模型
FloatProperty的setter中没有抛出未处理的异常,这类异常也会被包装成TargetInvocationException; - 检查视图控制器是否存在内存泄漏,比如持有VM的强引用导致无法正常释放。
内容的提问来源于stack exchange,提问作者jordiware
相关产品推荐
相关产品推荐

