UITableView - 破坏性UIContextualAction不会重新加载数据

时间:2017-10-12 16:03:15

标签: ios iphone swift xcode ios11

我正在尝试使用iOS 11方式在表格视图行中添加滑动操作。我想添加删除行的操作。

我的测试表视图显示0到9之间的数字,数据源是一个简单的整数数组,名为numbers

class ViewController: UIViewController {
    var numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
}

当我选择一行时,我会打印相关的numbers

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    print(numbers[indexPath.row])
    tableView.deselectRow(at: indexPath, animated: true)
}

我实现了新的代理trailingSwipeActionsConfigurationForRowAt,如下所示:

func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {

    let delete = UIContextualAction(style: .destructive, title: "Delete") { (_, _, completionHandler) in
        self.numbers.remove(at: indexPath.row)
        completionHandler(true)
    }

    return UISwipeActionsConfiguration(actions: [delete])
}

当我在一行上滑动时,删除工作正常。但是,这是我的问题,当我在删除后选择另一行时,关联的IndexPath是错误的......

示例:

  • 我选择第一行,打印的值为0:OK。
  • 我删除了第一行。
  • 我选择新的第一行,打印的值为2,因为传入的IndexPath参数是第1行,而不是第0行:不行。

我做错了什么?

2 个答案:

答案 0 :(得分:4)

重要的是要记住,有一个模型,你的案例中的numbers数组,以及一个视图,即显示的单元格。从numbers中删除元素时,您只更新模型。

在大多数情况下,正如您编写的那样,之后不久会出现错误,因为模型与视图不同步。

但是,我的测试表明,当样式为.destructive并且您将true传递给completionHandler时,Apple会为您删除该行。这就是你看到该行消失的原因。但是有些事情并不完全正确,我无法找到任何文件。

与此同时,只需这样做:

self.numbers.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .automatic)
completionHandler(true)

永远记住,如果您使用模型进行更改,则需要更新视图。

答案 1 :(得分:0)

使用true调用完成处理程序通过删除单元格来更新视图是非常令人困惑的,但是不更新表视图的概念,即哪个剩余单元格位于哪个索引路径。

围绕这个的文档很少,所以我运行了一个测试,发现调用完成处理程序true FIRST 然后调用deleteRows会导致“最正确“动画。

首先调试完成的批量更新:

tableView.beginUpdates()
completion(succeeded)
users.remove(at: indexToRemove)
tableView.deleteRows(at: [indexPath], with: .automatic)
tableView.endUpdates()

完成批量更新,名为second:

tableView.beginUpdates()
users.remove(at: indexToRemove)
tableView.deleteRows(at: [indexPath], with: .automatic)
completion(succeeded)
tableView.endUpdates()

首先调用完成:

completion(succeeded)
users.remove(at: indexToRemove)
tableView.deleteRows(at: [indexPath], with: .automatic)

完成第二次

users.remove(at: indexToRemove)
tableView.deleteRows(at: [indexPath], with: .automatic)
completion(succeeded)

图像中期动画:

enter image description here

右侧面板的剩余单元格被正在移除的单元格部分覆盖,而左下方面板则从某处显示白色视图。