【问题标题】:Getting loaded vs visible cells on a UITableView or UICollectionView在 UITableView 或 UICollectionView 上加载与可见单元格
【发布时间】:2017-01-01 07:11:18
【问题描述】:

随着 iOS 10 的推出,我们似乎将拥有prefetching enabled by default on UITableView and UICollectionViews。这意味着屏幕上未显示的单元格将在用户实际看到它们之前被获取。

以下是一些相关的方法:

UITableView:

UICollectionView:

所有这些都在描述中特别提到“可见”。随着 iOS 10 中预取的引入,我如何区分预取的单元格和当前可见的单元格?

换句话说:

  1. 如何获取所有可见单元格?
  2. 如何获取所有已加载的单元格?

UITableView 或 UICollectionView 上似乎没有任何新的 API 可以帮助解决这个问题。

【问题讨论】:

标签: uitableview uicollectionview uicollectionviewcell ios10


【解决方案1】:

TL;DR

  • 按字面意思在函数名称中使用visible
  • UITableView 的行为与 iOS 9 中的行为相同。
  • 如果您想在 iOS 10 上的 UICollectionView 中以不同方式处理已加载单元格和可见单元格,则需要进行一些记账。

UITableView 和 UICollectionView 在预取方面表现得非常不同。

首先要注意的是,预取cells和预取data是有区别的:

  • 预取单元格是指在单元格实际显示在屏幕上之前调用cellForRowAtIndexPath。这会导致您的单元格不在屏幕但仍在加载的情况。
  • 预取数据 指的是prefetchDataSource 方法,它通知您将在屏幕上显示的indexPaths。调用此方法时您没有对单元格的引用,并且调用此方法时您不会返回单元格。相反,此方法应该执行一些操作,例如触发网络请求以下载将显示在单元格中的图像。

注意:在所有这些场景中,假设在任何给定时间都可以显示 8 个单元格。

UITableView:(选项:no prefetchingprefetch data

  • 永远不会预取单元格。换句话说,它永远不会在未显示的indexPath 上调用cellForRowAtIndexPath
  • 因此,UITableView 上没有 isPrefetchingEnabled 属性。
  • 您可以使用prefetchDataSource 选择预取数据
  • 请注意,尽管表格视图看起来确实是less aggressive with reusing cells,但当重复使用的单元格重新出现在屏幕上时,它似乎仍然调用cellForItemAtIndexPath。 (尽管我可能需要对此进行更多调查,尤其是对于集合视图。)

UICollectionView:(选项:no prefetchingprefetch cellsprefetch cells and data

  • 默认预取单元格。换句话说,它会为不会立即显示的单元格调用cellForItemAtIndexPath
  • 仅当用户在集合视图上向上或向下滚动时才会开始预取单元格。换句话说,当视图被加载时,您将收到 8 次对 cellForItemAtIndexPath 的调用。只有当用户向下滚动时,它才会开始询问不可见的单元格(例如,如果您向下滚动以显示 2-10,它可能会询问 11-14)。
  • 当预取的、不可见的单元格出现在屏幕上时,它不会再次调用cellForItemAtIndexPath。它会假设您第一次执行的实例化仍然有效。
  • 您可以使用prefetchDataSource 选择预取数据
  • prefetchDataSource 只对初始加载有用。例如,在上述相同的场景中,当显示前 8 个单元格时,它可能会触发对单元格 9-14 的数据的预取。但是,一旦调用了这个初始方法,之后就没有用了。这是因为cellForItemAtIndexPath 将在每次调用prefetchItemsAt 后立即被调用。例如,您会立即收到prefetchItemsAt:[14, 15],然后是cellForItemAt:14cellForItemAt:15
  • 您可以通过设置isPrefetchingEnabled = false 选择退出所有预取行为。这意味着您不能使 UICollectionView 的行为类似于带有prefetchDataSource 的 UITableView。或者,换句话说,你不能只拥有一个 UICollectionView prefetch data

两者都

  • visibleCellsindexPathsForVisibleRowscellForItemAtIndexPath 完全按照他们的说法:他们只处理 可见 单元格。在我们相同的场景中,如果我们加载了 20 个单元格,但屏幕上只有 8 个单元格可见。所有这 3 种方法都只会报告屏幕上的 8 个单元格。

那么这是什么意思呢?

  • 如果您使用的是 UITableView,则可以按原样使用它,而不必担心已加载单元格与可见单元格之间的差异。它们总是等价的。
  • 另一方面,对于 UICollectionView,如果您关心这种差异,则需要进行一些记账以跟踪已加载的不可见单元格与可见单元格。您可以通过查看数据源上的一些方法和委托方法(例如 willDisplayCell、didEndDisplayingCell)来做到这一点。

【讨论】:

  • "如果您使用的是 UITableView,您可以按原样使用它,而不必担心已加载单元格与可见单元格之间的差异。它们始终是等效的" 确实如此细胞。问题在于数据。当表格视图首次出现时,prefetchRowsAt 对于最初可见的行不调用。那么你应该如何在不复制所有代码的情况下获取这些行的数据呢?我认为这是一个严重的错误。我知道如何解决它,但我不应该这样做。这些行应该是列表中的第一个以进行预取 - 而它们不是。
  • 他们最近也为 iOS 15.0 的 UITableView 启用了这个预取功能(参见视频:developer.apple.com/videos/play/wwdc2021/10252)。我的后续问题(对于启用预取的集合视图)是,当一个单元格滚动到可见性之外时,didEndDisplaying 被调用,但如果它自动反弹回视图(例如,它是第一个单元格和唯一的单元格),是不是预计cellForItemAtIndexPath 也会再次被调用?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 2015-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多