iOS UITableView:"cellForRowAtIndexPath"和"willDisplayCell:forRowAtIndexPath:"之间的区别是什么?

may*_*yue 30 uitableview ios

正如这个问题的标题中提到:有什么之间的"差异cellForRowAtIndexPath"和" willDisplayCell:forRowAtIndexPath?:"`

我认为单元格配置可以在cellForRowAtIndexPathwillDisplayCell: forRowAtIndexPath:"!

Glo*_*del 23

你是对的,单元配置可以(理论上)在两种方法中完成.

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

由于配置单元通常取决于您要显示的数据,cellForRowAtIndexPath:因此目前是进行单元配置的最常见位置.(我甚至不记得使用willDisplayCell:forRowAtIndexPath:).

还有一个值得注意的例外情况:当你使用的是故事板和静态细胞(而不是细胞的原型),你不能做任何有用cellForRowAtIndexPath:(因为dequeueReusableCellWithIdentifier:回报率nil),所以你必须在做配置willDisplayCell:forRowAtIndexPath:,viewWillAppear:或其他方法.

@NSDeveloper:你是对的.谢谢你的提示.

  • 使用[super tableView:tableView cellForRowAtIndexPath:indexPath]而不是dequeue ...来获取静态单元格. (6认同)
  • 它在iOS 10中变得很重要,其中collectionView(默认情况下)预先提取单元格.正如Apple所说:注意:启用预取时,集合视图委托上的collectionView:cellForItemAtIndexPath:方法在需要单元格之前被调用.为避免视觉外观不一致,请使用collectionView:willDisplayCell:forItemAtIndexPath:delegate方法更新单元格以反映视觉状态(如选择). (3认同)

Mar*_*ams 17

cellForRowAtIndexPath应该实际返回一个单元格实例.如果可能,它应该是重复使用的单元格.UITableViewDataSource协议需要此方法.这通常是您选择将在单元格中显示的数据的位置.对于动态单元格,在此处设置数据的同时设置UI属性(如选定状态)是很常见的.

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


iTS*_*gar 16

我想这回答了你的问题:

但是仍然存在非常重要的事情: tableView:cellForRowAtIndexPath:方法,它应该在UITableView的dataSource中实现,为每个单元调用并且应该快速工作.因此,您必须尽快返回重用的单元实例.

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

从UITableViews中的完美平滑滚动

  • 有没有实验数据证明这两者之间的区别? (4认同)

Vre*_*yan 6

尽管看似直观,但将在调用cellForRowAt indexPath:之后立即调用willDisplay cell :。

我有一个应用程序,可以从URLCache加载图像和视频,或者将其下载并显示在单元格中。我注意到,无论何时启动应用程序,所有视频和图像都会先加载,然后才能看到它们,我注意到这一点,因为在查看tableView的第一项时,我可以听到tableView的最后一个视频的音频。这是tableView中的8个项目。我打印到控制台以更好地了解委托函数调用的顺序。

结果:

  • 在第0行创建的单元格
    • 在第0行绘制提要单元
  • 在第1行创建的单元格
    • 在第1行绘制提要单元
  • 在第2行创建了单元格
    • 在第2行绘制提要单元
  • 在第3行创建了单元格
    • 在第3行绘制提要单元
  • 在第4行创建的单元格
    • 在第4行绘制提要单元
  • 在第5行创建的单元格
    • 在第5行绘制提要单元
  • 在第6行创建的单元格
    • 在第6行绘制提要单元
  • 在第7行创建的单元格
    • 在第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()
    }
}
Run Code Online (Sandbox Code Playgroud)

  • willDisplay 并不总是在每一行的 cellForRow 之后立即调用。例如,进入横向并滚动到大表格的底部,旋转到纵向,那些需要填充纵向屏幕的额外单元格都先批量调用 cellForRow,然后全部调用 willDisplayCell。 (2认同)

nem*_*ssm 5

我在willDisplayCell:使用自动布局和UITableViewAutomaticDimension. 重复使用的单元格的高度无法正确计算。NSLog 中的打印方法显示willDisplayCell:在之后调用heightForRowAtIndexPath:(在 iOS 10.2 模拟器上测试)

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}
Run Code Online (Sandbox Code Playgroud)

我认为这就是原因,因为将配置代码放入后问题就消失了cellForRowAtIndexPath:

PS 有一篇与@iTSangar 发布的链接和引用相反的文章:https://tech.zalando.com/blog/proper-use-of-cellforrowatindexpath-and-willdisplaycell/