iOS的UITableView:“cellForRowAtIndexPath”和“willDisplayCell:forRowAtIndexPath:”之间有什么不同

正如问题的标题所述:“ cellForRowAtIndexPath ”和“ willDisplayCellforRowAtIndexPath :”之间有什么区别?

我认为cellconfiguration可以在cellForRowAtIndexPathwillDisplayCell: forRowAtIndexPath: “!

你是对的,细胞configuration可以(理论上)在两种方法中完成。

但是,几乎所有的UITableView都有一个实现cellForRowAtIndexPath:的数据源cellForRowAtIndexPath:这是协议中必需的方法)。 另一方面, willDisplayCell:forRowAtIndexPath:它是委托的方法,而不是数据源)是可选的。

由于configuration单元通常依赖于要显示的数据cellForRowAtIndexPath:是目前最常用的单元configuration。 (我什至不记得使用willDisplayCell:forRowAtIndexPath:

有一个明显的例外:当你使用storyboard和静态单元格(而不是单元格原型)时,你不能在cellForRowAtIndexPath:做任何有用的事情cellForRowAtIndexPath:因为dequeueReusableCellWithIdentifier:返回nil ),所以你必须在willDisplayCell:forRowAtIndexPath:进行configurationwillDisplayCell:forRowAtIndexPath:viewWillAppear:或其他方法。

@NSDeveloper:你是对的。 感谢提示。

我认为这回答你的问题:

但是仍然非常重要的是: tableView:cellForRowAtIndexPath:方法,它应该在UITableView的dataSource中实现,为每个单元格调用并且应该工作得很快。 所以你必须尽可能快地返回重用单元实例。

此时不要执行数据绑定,因为屏幕上没有任何单元格。 为此,您可以使用tableView:willDisplayCell:forRowAtIndexPath:方法,它可以在UITableView的委托中实现。 在UITableView边界显示单元格之前调用的方法。

从UITableViews中完美的平滑滚动

cellForRowAtIndexPath实际上应该返回一个单元格实例。 在可能的情况下,它应该是一个重新使用的单元。 该方法是UITableViewDataSource协议所必需的。 这通常是您select将显示在单元格中的数据的位置。 使用dynamic单元格时,通常在设置数据的同时设置UI属性(如选定状态)。

willDisplayCell是可选的,之后被调用。 这是您显示之前最后一次自定义单元格的机会。 此时,单元实例已经被创build。 你可以在这里改变select状态等。 您不应该更改单元格的数据/结构或实例化任何新内容,而只是更改单元格的UI属性状态。 这通常与静态单元格一起使用。

我在willDisplayCell:遇到了单元configuration问题willDisplayCell:使用autolayout和UITableViewAutomaticDimension 。 重复使用的细胞高度计算不正确。 NSLog中的打印方法显示了willDisplayCell:heightForRowAtIndexPath:之后调用heightForRowAtIndexPath:在iOS 10.2模拟器上testing)

 cellForRowAtIndexPath: <NSIndexPath: 0x7c10daa0> {length = 2, path = 1 - 0} heightForRowAtIndexPath: <NSIndexPath: 0x7c10daa0> {length = 2, path = 1 - 0} heightForRowAtIndexPath: <NSIndexPath: 0x7c10daa0> {length = 2, path = 1 - 0} willDisplayCell: <NSIndexPath: 0x7c10daa0> {length = 2, path = 1 - 0} cellForRowAtIndexPath: <NSIndexPath: 0x7c4516f0> {length = 2, path = 1 - 1} heightForRowAtIndexPath: <NSIndexPath: 0x7c4516f0> {length = 2, path = 1 - 1} heightForRowAtIndexPath: <NSIndexPath: 0x7c4516f0> {length = 2, path = 1 - 1} willDisplayCell: <NSIndexPath: 0x7c4516f0> {length = 2, path = 1 - 1} 

我认为这是原因,因为在将configuration代码放入cellForRowAtIndexPath:后,问题已经消失cellForRowAtIndexPath:

PS有一个相反的文章到@iTSangar发布的链接和报价: https ://tech.zalando.com/blog/proper-use-of-cellforrowatindexpath-and-willdisplaycell/

尽pipe可能看起来很直观,但在调用cellForRowAt indexPath 之后立即调用willDisplay cell:。

我有一个应用程序,图像和video将从URLCache中加载或下载并显示在单元格中。 我注意到每当我开始我的应用程序,所有的video和图像将加载之前,我可以看到他们,我注意到这一点,因为我可以听到tableView的最后一个video的audio,同时看着tableView的第一个项目。 这是在tableView中的8个项目。 我打印到控制台以更好地了解委托函数调用的顺序。

结果:

  • 在第0行创build单元格
    • 在第0行绘制了饲料细胞
  • 在第1行创build单元格
    • 在第1行画出饲料细胞
  • 在第2行创build单元格
    • 在第2行画了饲料细胞
  • 在第3行创build单元格
    • 在第3行画了饲料细胞
  • 在第4行创build单元格
    • 在第4行画了饲料细胞
  • 在第5行创build单元格
    • 在第5行画了饲料细胞
  • 在第6行创build单元格
    • 在第6行画了饲料细胞
  • 在第7行创build单元格
    • 在第7行画了饲料细胞
  • 在第2行停止显示单元格
  • 在第3行停止显示单元格
  • 在第4行停止显示单元格
  • 在第5行停止显示单元格
  • 在第6行停止显示单元格
  • 在第7行停止显示单元格

代码:

  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "feedCell", for: indexPath) as! FeedCell print("Created cell at row \(indexPath.row)") let post = posts[indexPath.row] cell.post = post cell.viewController = self cell.configureCell() return cell } override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { if let feedCell = cell as? FeedCell{ print("Drew feed cell at row \(indexPath.row)") // only want download task to start when the cell will display if feedCell.post.isVideo { feedCell.loadVideo() } else { feedCell.loadImage() } } } override func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) { print("Stopped showing cell at row \(indexPath.row)") if let feedCell = cell as? FeedCell{ feedCell.player?.pause() } }