iOS的UITableView:“cellForRowAtIndexPath”和“willDisplayCell:forRowAtIndexPath:”之间有什么不同
正如问题的标题所述:“ cellForRowAtIndexPath
”和“ willDisplayCell
: forRowAtIndexPath
:”之间有什么区别?
我认为cellconfiguration可以在cellForRowAtIndexPath
或willDisplayCell: 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() } }