取消选择段时出现超出界限错误

时间:2014-03-20 10:51:35

标签: ios xamarin.ios xamarin uisegmentedcontrol

每当用户重新点击选定的段时,我都会尝试以编程方式从Xamarin中取消选择UISegmentedControl。我创建了一个继承的类,它将确定是否需要这个,但每当我尝试将SelectedSegment设置为-1时,应用程序就会爆炸,抛出一个超出范围的异常。

public class UIDeselectableSegmentedControl : UISegmentedControl
{
    private int previouslySelectedIndex = -1;

    private bool isIOS7
    {
        get
        {
            return UIDevice.CurrentDevice.CheckSystemVersion(7, 0);
        }
    }

    public UIDeselectableSegmentedControl()
    {
        this.ValueChanged += UIDeselectableSegmentedControl_ValueChanged;
    }

    void UIDeselectableSegmentedControl_ValueChanged(object sender, EventArgs e)
    {
        if (previouslySelectedIndex == this.SelectedSegment)
        {
            this.SelectedSegment = -1;
        }
        previouslySelectedIndex = this.SelectedSegment;
    }

    public override void TouchesBegan(NSSet touches, UIEvent evt)
    {
        int initialIndex = this.SelectedSegment;

        base.TouchesBegan(touches, evt);

        //Pre-iOS7 Segment Changes are present in Touches Began
        if (!isIOS7) CheckSelectedSegment(initialIndex, this.SelectedSegment);

    }

    public override void TouchesEnded(NSSet touches, UIEvent evt)
    {
        int initialIndex = this.SelectedSegment;

        base.TouchesEnded(touches, evt);

        //Post-iOS7 Segment Changes are present in Touches Ended
        if (isIOS7) CheckSelectedSegment(initialIndex, this.SelectedSegment);

    }

    /// <summary>
    /// Compare the SelectedSegment with the Current Index value. If it is the same, raise the Value Changed event.
    /// </summary>
    /// <param name="index">Currently Selected Segment</param>
    private void CheckSelectedSegment(int oldIndex, int newIndex)
    {
        if (oldIndex == newIndex)
        {
            this.SendActionForControlEvents(UIControlEvent.ValueChanged);
        }
    }

}

如果我将其更改为this.SelectedSegment = 0,则只要您重新点击另一个选定项目,控件就会成功强制SegementedControl到第一个项目,但如果我将其设置为-1,那么它抛出以下异常:

  

*由于未捕获的异常'NSRangeException'而终止应用程序,原因:'* - [__ NSArrayM objectAtIndex:]:索引4294967295超出边界[0 .. 1]'

我应该以不同的方式取消选择细分吗?根据{{​​3}}回答,这是Objective-C中的正确方法,而对SelectedSegment的元数据注释表明这是正确的:

//
// Summary:
//     The index of the selected segment.
//
// Remarks:
//     Set to -1 to turn off the currently selected segment. If MonoTouch.UIKit.UISegmentedControl.Momentary
//     == true the SelectedSegment property is ignored.

1 个答案:

答案 0 :(得分:0)

在典型的形式中,我认为我已经解决了自己的问题。我不确定为什么(也许有人可以澄清这一点),但这似乎与尝试更改SelectedSegment事件中的ValueChanged有关。可能是某种突变异常。

我已经重新编写了代码,因此在TouchesEnded / Began中调用的方法只是直接进行更改,而不是强制调用ValueChanged并自行更改它。在某种程度上,这更有意义,因为ValueChanged正在对变化作出反应 - 它可能不应该负责进行变更:

public class UIDeselectableSegmentedControl : UISegmentedControl
{
    private bool isIOS7
    {
        get
        {
            return UIDevice.CurrentDevice.CheckSystemVersion(7, 0);
        }
    }

    public override void TouchesBegan(NSSet touches, UIEvent evt)
    {
        int initialIndex = this.SelectedSegment;

        base.TouchesBegan(touches, evt);

        //Pre-iOS7 Segment Changes are present in Touches Began
        if (!isIOS7) DeselectSegmentIfApplicable(initialIndex, this.SelectedSegment);

    }

    public override void TouchesEnded(NSSet touches, UIEvent evt)
    {
        int initialIndex = this.SelectedSegment;

        base.TouchesEnded(touches, evt);

        //Post-iOS7 Segment Changes are present in Touches Ended
        if (isIOS7) DeselectSegmentIfApplicable(initialIndex, this.SelectedSegment);

    }

    /// <summary>
    /// Compare the SelectedSegment with the Current Index value. If it is the same, raise the Deselect the Segment.
    /// </summary>
    /// <param name="oldIndex">the previously selected segment</param>
    /// <param name="newIndex">The newly selected segment</param>
    private void DeselectSegmentIfApplicable(int oldIndex, int newIndex)
    {
        if (oldIndex == newIndex)
        {
            this.SelectedSegment = -1;
        }
    }
}