使用removeAtIndex在Swift中的索引超出范围

时间:2016-05-03 00:11:29

标签: swift

我尝试删除NSUserDefaults中的元素,该元素与单击按钮时stockSymbol的值相同。我的想法是将NSUserDefaults转换为数组并使用removeAtIndex删除该元素。这是我的代码。

@IBAction func buttonFilledStarClicked(sender: AnyObject) {
    NSLog("Filled star clicked")
    self.buttonFilledStar.hidden = true
    self.buttonEmptyStar.hidden = false

    var Array = NSUserDefaults.standardUserDefaults().objectForKey("favorites")! as! [String]
    var countArray = (NSUserDefaults.standardUserDefaults().objectForKey("favorites")! as! [String]).count - 1


    for i in 0...countArray {
        if stockSymbol! == Array[i] {
            NSLog("i is : \(i)")
            Array.removeAtIndex(i)
        }
        else {}
    }

    NSLog("Array is: \(Array), countArray is: \(countArray)")

}

然而,它有“超出索引”错误。 当我只评论Array.removeAtIndex(i)时,它就有用了。 数组看起来像这样 - [“aa”,“bb”,“测试!”,“测试!”] 有什么建议?提前谢谢。

4 个答案:

答案 0 :(得分:3)

因此,您可以通过对整个代码的影响最小化来解决错误的更改是简单地向后遍历索引:

for i in (0...countArray).reverse() {
    if stockSymbol! == Array[i] {
        NSLog("i is : \(i)")
        Array.removeAtIndex(i)
    }
    else {}
}

但最好的选择是使用Swift的filter

Array = Array.filter { $0 != stockSymbol }

关于崩溃发生原因的扩展说明......

我们举一个简化的例子。说我有以下array

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

我想从中删除所有奇数。使用你的第一个天真的方法,我可能写这样的逻辑:

for i in 0..<arr.count {
    if arr[i] % 2 != 0 {
        arr.removeAtIndex(i)
    }
}

看看每次迭代会发生什么。

在第一次迭代中,我们arr[i]1。这是一个奇数,所以我们removeAtIndex,我们的数组实际上看起来像这样:

[2, 3, 4, 5, 6, 7, 8, 9, 10]

数组的大小现在变小了 - 它只有9个元素。但是循环不像旧的C风格for循环那样工作,每次迭代都检查i < arr.count(这是为什么这个循环更快)的一部分。

但请注意我们向前迭代时发生的其他事情......

在第二次迭代中,i等于1,那么arr[i]给了我们什么?它给了我们3。我们甚至都没有检查2。在第一次迭代中,当i0时,它位于索引1。在第二次迭代中,当i1时,2位于索引0

因此,在第二次迭代中,我们会调用removeAtIndex i等于1并删除3

这种模式将持续几次迭代,直到我们得到偶数数组:

[2, 4, 6, 8, 10]

但这发生在i等于4的迭代之后,循环将尝试运行,直到i等于10

在循环的第六次迭代中,我们尝试访问数组的索引5处的元素。但是数组只有五个元素,因此最大的索引是4。当我们尝试访问索引5时,我们会崩溃。

答案 1 :(得分:2)

尝试找出哪些i可以提供index out of range结果。是0还是最后一个。也许你会找到一些其他有用的线索。

答案 2 :(得分:2)

你不应该从循环内部删除它,当你调用removeAtIndex(i)数组删除项目,所以你有少一个项目然后countArray ..所以你必须有另一个数组来记住你要删除的项目并将其移除到循环外..或更好的选择是使用过滤器

// Filter only strings that match stockSymbol
Array = Array.filter { $0 == stockSymbol! }

答案 3 :(得分:0)

首先,Array是一种类型,也许你可以调用:

var favourites = NSUserDefaults.standardUserDefaults().objectForKey("favorites")! as! [String]

然后,您不需要使用count arrays属性访问的数组计数变量。

最后,如果你正在迭代一个数组并删除一个元素,它总是会抛出&#34;索引的错误&#34;因为索引与开头不一样..

为了解决这个问题,您可以使用索引变量的两个指针,但我会做的是这样的:

var correctElements = favourites.filter({$0!=stockSymbol})