在UITableView或UICollectionView上加载vs可见单元格

Sen*_*ful 19 uitableview uicollectionview uicollectionviewcell ios10

随着iOS 10的推出,似乎我们将在UITableView和UICollectionViews上默认启用预取.这意味着在用户实际看到它们之前,将获取未在屏幕上显示的单元格.

以下是一些相关方法:

UITableView:

UICollectionView:

所有这些都在他们的描述中特别提到"可见".随着在iOS 10中引入预取,我如何区分预取的单元与当前可见的单元?

换一种说法:

  1. 我如何获得所有可见细胞?
  2. 我如何获得所有加载的单元格?

看起来UITableView或UICollectionView上没有任何新的API可以帮助解决这个问题.

Sen*_*ful 27

TL; DR

  • 就拿visible函数名字面上.
  • UITableView的行为与iOS 9中的行为相同.
  • 如果要在iOS 10上的UICollectionView中以不同方式处理加载与可见单元格,则需要执行一些簿记.

在预取时,UITableView和UICollectionView的行为看起来非常不同.

首先要注意的是预取单元格和预取数据之间存在差异:

  • 预取单元格是指cellForRowAtIndexPath在单元格实际显示在屏幕上之前调用的单元格.这将启用您具有屏幕外但仍加载的单元格的方案.
  • 预取数据是指prefetchDataSource告知您indexPaths将在屏幕上显示的方法.调用此方法时,您没有对单元格的引用,并且在调用此方法时不返回单元格.相反,此方法应该执行诸如触发网络请求以下载将在单元格中显示的图像之类的操作.

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

UITableView :(选项:no prefetching,或prefetch data)

  • 永远不会预取细胞.换句话说,它绝不会叫cellForRowAtIndexPathindexPath不显示.
  • 因此,isPrefetchingEnabledUITableView上没有属性.
  • 您可以选择启用预取数据使用prefetchDataSource.
  • 请注意,尽管表格视图在重用单元格时看起来似乎不那么激进,但是cellForItemAtIndexPath当重用的单元格返回到屏幕上时,它仍然会调用.(虽然我可能需要对此进行更多调查,尤其是对于集合视图.)

UICollectionView:(选项:no prefetching,prefetch cells,或prefetch cells and data)

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

对于两者:

  • visibleCells,indexPathsForVisibleRowscellForItemAtIndexPath完全按照他们的说法做:他们只处理可见细胞.在我们的相同场景中,如果我们加载了20个单元格,但屏幕上只能看到8个单元格.所有这3种方法仅报告8个屏幕上的细胞.

那么这是什么意思?

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

  • 他们最近也为 iOS 15.0 的 UITableView 启用了此预取功能(请参阅视频:https://developer.apple.com/videos/play/wwdc2021/10252/)。我接下来的问题(对于启用预取的集合视图)是,当单元格滚动到不可见状态时,会调用“didEndDisplaying”,但如果它自动弹回到视图中(例如,它是第一个单元格,也是唯一的单元格),是吗?预计还会再次调用“cellForItemAtIndexPath”? (2认同)