You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:31:06