Swift:致命错误:从tableview中删除项目时数组索引超出范围

时间:2016-02-18 05:50:03

标签: swift uitableview

我已经设置了一个表来从数据库中提取数据。用户可以通过复选框(table.editing = true,iirc)和删除按钮手动删除表格(以及数据库)中的项目。这可以一次完成一个,也可以一次完成。

不幸的是,每当我检查所有内容以进行删除时,应用程序都会崩溃并出现以下错误:

  

致命错误:数组索引超出范围

如果我只选择并删除一个或任意数量的表行,则不会发生这种情况,只要我不选择所有内容。

这是删除按钮的代码:

typeof obj == 'function' || false

我可以想到,它正在尝试删除索引处的行,由于前一行也被删除,索引可能不再存在(?),但我不确定。

我尝试使用以下代码:

func deleteButtonPressed(sender: AnyObject) {
    if (self.pureSteamFormView.tableCalibration.editing == true) {
        if (self.pureSteamFormView.tableCalibration.indexPathsForSelectedRows!.count >= 1) {
            for indexPath in self.pureSteamFormView.tableCalibration.indexPathsForSelectedRows!.sort({ $0.row < $1.row}) {
                let calibTable : FormSteamPurityCalibration = self.steamPurityCalibrationTableList[indexPath.row] /* <--- ERROR HERE */

                DatabaseManager.getInstance().deleteData("FormSteamPurityCalibration", "ID = \(calibTable.ID)")

                self.steamPurityCalibrationTableList.removeAtIndex(indexPath.row)
            }
            self.pureSteamFormView?.tableCalibration.reloadData()
        }
    }
}

在它自己的for-loop块中,错误立即移动到那里。

我还尝试完全删除self.steamPurityCalibrationTableList.removeAtIndex(indexPath.row) 部分,依赖于removeAtIndex自动更新表,但它不起作用 - 数据从数据库中删除,但仍保留在表(尽管离开那个视图并返回那里更新表)。

有什么建议吗?感谢。

1 个答案:

答案 0 :(得分:1)

这里的问题是你要在较大的索引之前删除最低的索引。让我用一个例子来解释:

图片中有4个元素:

let array = ["Element1", "Element2", "Element3", "Element4"]

您正尝试删除索引1和3中的元素:

for index in [1, 3] {
    array.removeAtIndex(index)
}

您的程序将首先删除索引1处的元素,然后使用以下数组:

["Element1", "Element3", "Element4"]

在循环的第二遍中,它将尝试删除索引3处的元素。由于它已移至索引2,因此不再存在。

对此的一个解决方案是开始删除之前具有更大索引的元素,因此在您的代码中您可以更改

for indexPath in self.pureSteamFormView.tableCalibration.indexPathsForSelectedRows!.sort({ $0.row < $1.row}) {

for indexPath in self.pureSteamFormView.tableCalibration.indexPathsForSelectedRows!.sort({ $0.row > $1.row}) {

更好的解决方案是过滤您的数据数组,使其仅包含您希望保留的元素,而不是:

for indexPath in self.pureSteamFormView.tableCalibration.indexPathsForSelectedRows!.sort({ $0.row < $1.row}) {
    let calibTable : FormSteamPurityCalibration = self.steamPurityCalibrationTableList[indexPath.row]
    DatabaseManager.getInstance().deleteData("FormSteamPurityCalibration", "ID = \(calibTable.ID)")
    self.steamPurityCalibrationTableList.removeAtIndex(indexPath.row)
}
你可以这样做:

self.steamPurityCalibrationTableList.filter {
    if let index = self.steamPurityCalibrationTableList.indexOf ({ $0 })
    {
        for indexPath in self.pureSteamFormView.tableCalibration.indexPathsForSelectedRows! {
            if indexPath.row == index { return false }
        }

        return true
    }
}