UITableViewCell内容在单独重新加载单元格时闪烁

时间:2015-04-20 05:29:13

标签: ios objective-c performance uitableview asyncdisplaykit

我有一个链接到NSFetchedResultController的表格视图(即加载数据并跟踪数据的更改绑定到FRC)

我没有在我的单元格中使用AutoLayout(由于它在iOS 8中引入了巨大的性能下降)。我布置了我的细胞'在单元格中手动填写内容(使用-(void)layoutSubviews)。另外,行的高度是根据内容计算的,并且可以正确缓存/无效。

如果与我的数据相关的任何条件发生更改,相关单元格会单独更新(实施了-(void)controllerWillChangeContent:...-(void)controllerDidChangeContent:...个委托方法),行更新动画为:UITableViewRowAnimationNone

这里的问题是,我的细胞有透明的背景,我可以看到一些视觉噪音(很可能是实际的细胞被垂直拉伸,我无法肯定地说,因为它们真的是短暂的和短暂的)在[self.tableView reloadRowsAtIndexPaths:...];期间。

我尝试了很多事情无济于事!

以下是我尝试过的不起作用的事情:

  • 实施-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath,返回估算高度的准确值。
  • 设置self.tableView.rowHeight=UITableViewAutomaticDimension;,帮助很多,但没有解决它。
  • [self.tableView beginUpdates];上禁用动画并在[self.tableView endUpdates];
  • 之后启用
  • 从细胞中移除所有子视图' -(void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
  • 中的内容

有点帮助的事情:

  • 使细胞不透明(即为细胞设置背景颜色)。很奇怪,这些文物似乎都在实际的细胞内容之下。

更多信息

  • 我的大多数细胞' content是来自AsyncDisplayKit(ASTextNode,ASImageNode)的节点,但用它们的UIKit对应物替换它们并不能解决问题。
  • 我的所有视觉更新都发生在主线程上。我总是确保这一点。
  • 问题不是普遍存在,而是经常存在。如果它有帮助,它们似乎会在第二个细胞插入后发生更多。
  • 在我的单元格中记录方法-(void)layoutSubviews表明,每次更新时,具有更新条件的单元格会连续重新加载3次,而其他单元格只会更新一次。我并未强制任何[cell layoutIfNeeded];[cell setNeedsLayout];任何地方。
  • 使用[self.tableView reloadData];重新加载整个表视图对我来说不是一个选项。

其他更多信息

  • 使细胞变得不透明导致细胞一次性排列!奇怪!

最后,对不起,我无法分享任何实际代码,因为它不是测试项目,并且实现的复杂性使得任何代码共享都是徒劳的,除非作为一个整体被理解

感谢您的时间。

6 个答案:

答案 0 :(得分:18)

我在使用reloadRowsAtIndexPath时也遇到了闪烁UITableViewCell的问题,所以我做的是 -

     [UIView setAnimationsEnabled:NO];
     [self.tableView beginUpdates];

     [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil]
                                               withRowAnimation:UITableViewRowAnimationNone];
     [self.tableView endUpdates];
     [UIView setAnimationsEnabled:YES];

重新加载单元格时,上面的代码段在单元格上没有动画。

答案 1 :(得分:10)

是的,您可以使用performWithoutAnimation(Swift版本)从@ Sandy的答案中获得类似的结果

UIView.performWithoutAnimation {
      self.tableView.reloadRows(at: [indexPath], with: .none)
}

答案 2 :(得分:5)

如果有人遇到同样的问题:

如果您正在计算单元格高度及其元素,并且您依赖于NSIndexPath来查询任何数据或条件,请始终检查您的索引路径是否有效(而不是nil)。返回索引路径的大多数UITableView方法(例如-(NSIndexPath *)indexPathForCell:..等)可能会返回nil值,并会向您发送调试视图的螺旋。

在我的情况下,我有一种方法来确定我的细胞是否应该有一个标题,为此,我检查了它是第一个细胞或自上一个细胞以来病情发生了变化。问题是indexPath.row == 0即使索引路径实际上是nil也是如此(这是Objective-C中nil为0的概念问题)。所以片刻之后,我的细胞会认为它有一个标题!

我觉得有点愚蠢没有检查nil索引路径,但我认为分享它可能有一天会帮助某人。

答案 3 :(得分:3)

快速使用它并减少闪烁

let visibleIndexs = self.ContentTableview.indexPathsForVisibleRows! as NSArray
        print(visibleIndexs)
        for indx in visibleIndexs {
            if self.imgDownloadedIndexs!.containsObject(indx) {
                  UIView.setAnimationsEnabled(false)
                self.ContentTableview.beginUpdates()
                self.ContentTableview.reloadRowsAtIndexPaths([indx as! NSIndexPath], withRowAnimation:.None)
                self.ContentTableview.endUpdates()
                 UIView.setAnimationsEnabled(true)
                self.imgDownloadedIndexs?.removeObject(indx)

            }

答案 4 :(得分:0)

删除rowHeightAtIndexPath方法将解决此问题。确保您为故事板上的表格单元设置了固定的高度。

答案 5 :(得分:0)

tableView 自定义单元格不可点击和闪烁。这是因为单元格动画。添加以下代码后,单元格可以点击并且工作正常。 这种情况很正常,在运行UITestCase的时候也有可能出现。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
   UIView.performWithoutAnimation {
      self.tableView.reloadRows(at: [indexPath], with: .none)
  }
return cell
}