在从UITableView中删除项目之后,索引超出范围
请帮我看看我的错误是什么 我有一个表视图,数据源是一个名为items的数组。 从items数组中删除一个项目后,调用cellForRowAt方法,参数indexPath.row与items.count相等。 这只会发生,当行数足够一个项目不在表视图的视图。 发生时会导致严重的错误(索引超出范围)。 在这种情况下使用黑客攻击,并且IndexPath.row的值会减less。
请看下面的图片:
以下代码为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
UPDATE
我试过了,下面这个非常简单的代码也受到影响:
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) } } }
如何重现:
- 向下滚动到Y是屏幕上的最后一个项目
- 尝试删除Y滑动到左侧
- 并获得以下错误
你的删除代码看起来很好,但是你不应该在你的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相关的bug。在Xcode 8.x上运行良好。 OP会就此向苹果提交一个bug 。