简体   繁体   English

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

[英]Swift: fatal error: Array index out of range on deleting item from a tableview

I've setup a table to pull data from a database. 我已经设置了一个表来从数据库中提取数据。 The user can manually delete items from the table (and thus the database) via checkbox (table.editing = true, iirc) and a delete button. 用户可以通过复选框(table.editing = true,iirc)和删除按钮从表(从而从数据库)中手动删除项目。 This can be done one at a time, or all at a time. 这可以一次完成,也可以一次完成。

Unfortunately, whenever I check everything for deletion, the app crashes with the following error: 不幸的是,每当我检查所有要删除的内容时,应用都会崩溃并显示以下错误:

fatal error: Array index out of range 致命错误:数组索引超出范围

This does not happen if I select and delete only one or any number of the table rows, as long as I don't select everything. 如果我仅选择和删除一个或任意数量的表行,只要我不选择所有内容,就不会发生这种情况。

Here's my code for the delete button: 这是我的删除按钮代码:

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()
        }
    }
}

Near as I can figure, it is attempting to remove the row at an index, an index that may no longer exist (?) due to the previous row also being deleted, but I'm not sure about that. 据我所知,它正在尝试删除索引处的行,由于上一行也被删除了,所以该索引可能不再存在(?),但是我不确定。

I tried putting the following code: 我尝试放入以下代码:

self.steamPurityCalibrationTableList.removeAtIndex(indexPath.row)

In its own for-loop block, and the error promptly move there. 在它自己的for循环块中,错误立即移到那里。

I also tried removing the removeAtIndex part completely, relying on the reloadData() to perhaps update the table automatically, but it doesn't work - the data is deleted from the database, but remains on the table (although moving away from that view and going back there updates the table). 我还尝试完全删除removeAtIndex部分,依靠reloadData()也许自动更新表,但是它不起作用-数据已从数据库中删除,但仍保留在表中(尽管远离该视图并返回那里更新表格)。

Any suggestions please? 有什么建议吗? Thanks. 谢谢。

Your problem here is that you are deleting the lowest indexes before the bigger ones. 您的问题在于,您正在删除最低索引,而不是较大索引。 Let me explain with an example: 让我用一个例子来解释:

Image you have 4 elements in your array: 图片您的数组中有4个元素:

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

You are trying to remove the elements at index 1 et 3: 您正在尝试删除索引1和3中的元素:

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

Your program will first remove element at index 1, leaving you with the following array: 您的程序将首先删除索引1处的元素,剩下以下数组:

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

On the second pass of the loop it will try to remove the element at index 3. Which does not exist anymore because it has moved to index 2. 在循环的第二遍,它将尝试删除索引3处的元素。该元素已不存在,因为它已移至索引2。

One solution to this is to start removing element with the greater index before, so in your code you could change 一种解决方案是先删除索引较大的元素,因此可以在代码中进行更改

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

to

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

A better solution would be to filter your data array to include only the elements you whish to keep, so instead of: 更好的解决方案是对数据数组进行过滤,使其仅包含您希望保留的元素,因此,请不要:

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)
}

you could do: 你可以做:

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
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM