【问题标题】:UITableView - Destructive UIContextualAction does not reload dataUITableView - 破坏性 UIContextualAction 不会重新加载数据
【发布时间】:2017-10-12 16:03:14
【问题描述】:

我正在尝试使用 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行:不行。

我做错了什么?

【问题讨论】:

    标签: ios iphone swift xcode ios11


    【解决方案1】:

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

    在大多数情况下,当您对其进行编码时,您很快就会收到错误,因为模型与视图不同步。

    但是,我的测试表明,当样式为 .destructive 并且您将 true 传递给 completionHandler 时,Apple 会为您删除该行。这就是您看到该行消失的原因。但是有些地方不太对劲,我找不到任何关于它的文档。

    与此同时,请执行以下操作:

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

    请始终记住,如果您更改模型,则需要更新视图。

    【讨论】:

    • 谢谢!我对完成处理程序周围缺乏文档感到非常困惑。作为传递给UIContextualAction初始化器的闭包块中的参数之一,我想这不是我们可以定义的吗?
    【解决方案2】:

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

    这方面的文档非常少,所以我进行了测试,发现使用true FIRST 调用完成处理程序然后调用deleteRows 会产生“最正确”的动画。

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

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

    批量更新完成称为秒:

    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)
    

    图像中间动画:

    右侧面板都有剩余的单元格部分被要移除的单元格覆盖,而左下方的面板从某个地方引入了白色视图。

    【讨论】:

    • 另外,你有没有想过在批量更新前后调用完成块?当我这样做时,我会得到像上面的“CompletionFirst”示例一样的动画。
    猜你喜欢
    • 2011-09-18
    • 2013-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多