使用动画重新加载表格视图单元格(Swift)

17

有没有一种方法可以重新加载具有多个部分和动画的特定UITableView单元格?

我一直在使用:

self.TheTableView.reloadSections(NSIndexSet(index: 1), withRowAnimation: UITableViewRowAnimation.Right)

这将使该部分中的所有单元格进行动画处理。另一个选项是使用:

self.TheTableView.reloadRowsAtIndexPaths(<#indexPaths: [AnyObject]#>, 
                                         withRowAnimation: <#UITableViewRowAnimation#>)

编辑:

在使用 reloadRowsAtIndexPaths 后

应用程序因未捕获的异常“NSInternalInconsistencyException”而终止,原因是“无效更新:部分1中的行数无效。 更新后现有部分中包含的行数(5)必须等于更新前该部分中包含的行数(4),加上或减去从该部分中插入或删除的行数(0插入,0删除)以及加上或减去移入或移出该部分中的行数(0移入,0移出)。

试图通过将对象附加到数组中来找到平滑重载表格视图的方法。

在 reloadRowsAtIndexPaths 之前调用 TheTableView.reloadData() 可以工作,但动画效果不稳定。还有其他方法吗?


发生了什么事情?! - user1019042
也许你应该看一下这篇文章 https://dev59.com/nGEi5IYBdhLWcg3wwecN - Bjørn Ruthberg
4个回答

13
为什么不直接重新加载单元格呢?indexPath 包含了区域和行数信息,所以只需跟踪想要重新加载的区域并在该数组中填充索引即可。
var indexPath1 = NSIndexPath(forRow: 1, inSection: 1)
var indexPath2 = NSIndexPath(forRow: 1, inSection: 2)
self.tableView.reloadRowsAtIndexPaths([indexPath1, indexPath2], withRowAnimation: UITableViewRowAnimation.Automatic)

根据您的评论,您希望更改数组并使tableView在更改时进行动画。如果是这种情况,您应该考虑使用UITableView的beginUpdates()和endUpdates(),甚至可以使用NSFetchedResultsController,以便它可以干净地处理所有更新动画。

self.tableView.beginUpdates()
// Insert or delete rows
self.tableView.endUpdates()

我建议使用NSFetchedResultsController,如果你正在使用Core Data,因为它可以简化整个过程。否则,你需要自己处理这些变化。换句话说,如果你的数组发生了变化,你需要使用beginUpdates()和endUpdates()手动删除或插入表格视图中的行。 如果你没有使用Core Data,请研究this以了解如何处理它们。

由于未捕获的异常“NSInternalInconsistencyException”,应用程序终止,原因是:“无效更新:第1节中的行数无效。更新后现有节中包含的行数(5)必须等于更新前该节中包含的行数(4)加上或减去从该节中插入或删除的行数(0插入,0删除)以及加上或减去移入或移出该节的行数(0移入,0移出)。 - William Larson
这个方法可能可行,但在调用reloadRowsAtIndexPaths之前我需要重新加载数据。我会稍微调整一下。也许在这个命令之前调用ReloadData? - William Larson
如果您想要进行干净的动画,请勿调用reloadData。如果您的数据正在更改,请查看beginUpdates()和endUpdates()。UITableViewControllers利用此功能使事情变得更加容易(如果适合您的应用程序模型)。 - Mark McCorkle
所以我尝试了你的解决方案,但无论我把beginUpdates()和endUpdates()放在哪里,似乎都不能解决崩溃的问题。我基本上有一个IBAction,它将数据附加到数组中,还需要重新加载tableView并仅动画显示特定添加的单元格。 - William Larson
在调用 endUpdates 时(或者在调用 reloadRowinsertRowsAtIndexPathsdeleteRowsAtIndexPaths 时没有调用 beginUpdates),委托必须设置为在请求时返回正确的行数和单元格。 - Joseph Lord

5

在Swift 3.0中

我们可以重新加载表格视图中特定区域的特定行。

let indexPath = IndexPath(item: 2, section: 0)
self.tableView.reloadRows(at: [indexPath], with: .automatic)

3
如果您想在Swift 3.0中重新加载单个部分,可以执行以下操作:
tableView.reloadSections(IndexSet(integer: 0), with: .automatic)

3

官方文档中对IndexSet的定义:

管理一组整数值的Set,这些值通常用作Cocoa API中的索引类型。有效整数值范围在(0, INT_MAX-1)之间。超出此范围的任何值都是错误的。

因此,IndexSet是关于索引的集合,只需将一些Int值放在[ ]中即可。

// for reload one section
tableView.reloadSections([section], with: .automatic)
// or using like this
tableView.reloadSections(IndexSet(integer: section), with: .automatic)

// for reload multi sections
tableView.reloadSections([1, 2, 3, section], with: .automatic)

1
请添加更多关于您的答案的描述和/或信息,以及它如何解决所提出的问题,以便其他人可以轻松理解,无需请求澄清。 - koceeng
嗨@koceeng,我是Swift的新手。据我所知,IndexSet是一个关于索引的集合,并且官方文档在定义IndexSet时进行了解释: ///管理整数值的“Set”,这些值通常用作Cocoa API中的索引类型。 ///有效整数值的范围为0..<INT_MAX-1。此范围之外的任何内容都是错误的。因此,我们可以将其用作集合使用:将一些Int值放入[ ]中。 - Junhang Lv
不要误会,您的回答在这里非常受欢迎,我们非常感激。但是如果您提供一些详细描述,那么它将更有趣且更易于理解。实际上,您上面的评论非常好,可以在您的答案中提到。因为很多时候,寻求答案的人会忽略评论。您可以编辑您的答案并包含您上面的评论。祝您愉快 :) - koceeng
1
嗨@koceeng,实际上,我对我的糟糕英语感到焦虑。谢谢你的建议,我已经重新编辑了它。 - Junhang Lv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接