【问题标题】:Index out of range after item has been deleted from UITableView从 UITableView 中删除项目后索引超出范围
【发布时间】:2017-09-16 08:30:24
【问题描述】:

请帮我找出我的错误。我有一个表格视图,数据源是一个称为项目的数组。从 items 数组中删除一项后,调用 cellForRowAt 方法并且参数 indexPath.row 与 items.count 相等。仅当行数刚好足以使一个项目超出表视图的视图时才会发生这种情况。 当它发生时,它会导致致命错误(索引超出范围)。在这种情况下使用 hack 并减少 IndexPath.row 的值。

请看下图:

cellForRowAt 的以下代码:

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell", for: indexPath) as! ItemCell

    var i = indexPath.row
    if i >= items.count { i = items.count - 1 } //XXX: hack! Sometimes called with indexPath.row is equal with items.count :(
    cell.set(items[i])

    return cell
}

删除的代码如下:

    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath)
{
    if (editingStyle == UITableViewCellEditingStyle.delete)
    {
        items.remove(at: indexPath.row)

        tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.fade)
    }
}

我认为不相关,但我使用的是 iOS 11.0

更新

我试过了,下面很简单的代码也受影响:

    class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate
{
    var items = ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]

    override func viewDidLoad()
    {
        super.viewDidLoad()
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
        return items.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    {
        let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell", for: indexPath)
        cell.textLabel?.text = "\(items[indexPath.row])"

        return cell
    }

    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath)
    {
        if (editingStyle == UITableViewCellEditingStyle.delete)
        {
            items.remove(at: indexPath.row)
            tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.fade)
        }
    }
}

如何重现:

  1. 向下滚动到 Y 是屏幕上的最后一项

  1. Y向左滑动尝试删除

  1. 并出现以下错误

【问题讨论】:

  • 您在cellForRowAt 中的“黑客”不应该存在。如果你真的需要它,那么你的numberOfRowsInSection 就有问题。
  • 我的 numberOfRowsInSection 返回:return items.count
  • 在删除行(items 中的索引项)后尝试重新加载 tableVew tableView.reloadData(),以便从新的 items.count 更新 numberOfRowsInSection
  • 我在发布之前尝试过,但遇到了同样的错误。 :(但是谢谢!

标签: ios swift uitableview delete-row


【解决方案1】:

您的删除代码看起来不错,但您不应该做您在cellForRowAt 中所做的事情。改为这样做:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell", for: indexPath) as! ItemCell
    cell.set(items[indexPath.row])

    return cell
}

你的numberOfRowsInSection应该是这样的:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return items.count
}

更新:
我们刚刚确认这是与 Xcode 9 beta 和 iOS 11 相关的错误。在 Xcode 8.x 上运行良好。 OP 将就此向 Apple 提交bug

【讨论】:

  • 我的 numberOfRowsInSection 和你提到的一样。这就是为什么我不明白问题出在哪里。没有其他线程,因此无法通过其他方式修改 items 数组。
  • @EdmundElmer,如果您按照我在回答中的要求进行操作并且仍然无法正常工作,那么您的代码中还有其他内容无法正常工作。为问题添加更多代码,以便我们继续调查。
  • 谢谢,我将删除所有不必要且与问题无关的代码,并将发布整个控制器代码。再次感谢您的帮助!
  • 我尝试了一个尽可能简单的视图控制器,但我得到了同样的错误。 :(
  • @EdmundElmer,刚刚试用了你的代码,它对我有用...Here 是我的项目,结合你的代码试试吧。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-10
  • 1970-01-01
  • 2019-02-06
  • 1970-01-01
  • 2015-12-28
  • 2014-10-17
相关资源
最近更新 更多