在 UITableView 或 UICollectionView 上加载与可见单元格 [英] Getting loaded vs visible cells on a UITableView or UICollectionView
问题描述
随着 iOS 10 的推出,我们似乎将在 UITableView 上默认启用 预取和 UICollectionViews.这意味着屏幕上未显示的单元格将在用户实际看到它们之前被获取.
With the introduction of iOS 10, it seems like we're going to have prefetching enabled by default on UITableView and UICollectionViews. This means that cells that aren't displayed on the screen are going to be fetched before the user actually sees them.
以下是一些相关的方法:
Here are some relevant methods:
- cellForRowAtIndexPath::如果单元格不可见,则返回
nil
." - visibleCells:每个项目代表表格视图中的一个可见单元格".
- indexPathsForVisibleRows:每个项目代表表格视图中的可见行".
- cellForRowAtIndexPath:: returns "
nil
if the cell is not visible." - visibleCells: each item represents "a visible cell in the table view."
- indexPathsForVisibleRows: each item represents "a visible row in the table view."
- visibleCells:"返回集合视图显示的可见单元格的完整列表."
- indexPathsForVisibleItems:每个项目都代表集合视图中的一个可见单元格".
- cellForItemAtIndexPath::如果单元格不可见,则返回
nil
."
- visibleCells: "returns the complete list of visible cells displayed by the collection view."
- indexPathsForVisibleItems: each item represents "a visible cell in the collection view."
- cellForItemAtIndexPath:: returns "
nil
if the cell is not visible."
所有这些都在描述中特别提到可见".随着 iOS 10 中引入预取,我如何区分预取的单元格和当前可见的单元格?
All these specifically mention "visible" in their descriptions. With the introduction of pre-fetching in iOS 10, how would I distinguish between a cell that was pre-fetched vs. one that is currently visible?
换句话说:
- 如何获取所有可见单元格?
- 如何获取所有已加载的单元格?
UITableView 或 UICollectionView 上似乎没有任何新的 API 可以帮助解决这个问题.
It does not look like there are any new APIs on either UITableView or UICollectionView that can help with this.
推荐答案
TL;DR
- 按字面意思理解函数名称中的
visible
. - UITableView 的行为与 iOS 9 中的行为相同.
- 如果您想在 iOS 10 上的 UICollectionView 中以不同方式处理已加载单元格和可见单元格,则需要进行一些记录.
UITableView 和 UICollectionView 在预取方面表现得非常不同.
UITableView and UICollectionView appear to behave very differently when it comes to prefetching.
首先要注意的是,预取cells和预取data是有区别的:
First thing to notice is that there is a difference between prefetching cells and prefetching data:
- 预取单元格是指在单元格实际显示在屏幕上之前调用的
cellForRowAtIndexPath
.这会导致您的单元格不在屏幕但仍在加载的情况. - 预取数据 指的是
prefetchDataSource
方法,它通知您将在屏幕上显示的indexPaths
.调用此方法时您没有对单元格的引用,并且调用此方法时您不会返回单元格.相反,此方法应该执行一些操作,例如触发网络请求以下载将显示在单元格中的图像.
- Prefetching cells refers to the
cellForRowAtIndexPath
being called before the cell is actually displayed on screen. This enables the scenario where you have cells that are off-screen but still loaded. - Prefetching data refers to the
prefetchDataSource
methods which inform you aboutindexPaths
that are going to be displayed on screen. You do not have a reference to the cell when this method is called, and you do not return a cell when this method is called. Instead, this method should do things like fire off a network request to download an image that will be displayed in the cell.
注意:在所有这些场景中,假设在任何给定时间都可以显示 8 个单元格.
Note: In all of these scenarios, imagine there are 8 cells that can be displayed at any given time.
UITableView:(选项:no prefetching
,或prefetch data
)
- 永远不会预取 cells.换句话说,它永远不会在未显示的
indexPath
上调用cellForRowAtIndexPath
. - 因此,UITableView 上没有
isPrefetchingEnabled
属性. - 您可以选择使用
prefetchDataSource
预取 数据. - 请注意,尽管表格视图确实在重用单元格方面没有那么积极,但它似乎仍然当重用的单元格返回屏幕时调用
cellForItemAtIndexPath
.(尽管我可能需要对此进行更多调查,尤其是对于集合视图.)
- Does not prefetch cells, ever. In other words, it will never call
cellForRowAtIndexPath
on anindexPath
that isn't displayed. - As such, there is no
isPrefetchingEnabled
property on a UITableView. - You can opt-in to prefetching data by using the
prefetchDataSource
. - Note that although the table view does seem to be less aggressive with reusing cells, it still appears to call
cellForItemAtIndexPath
when the reused cell comes back on screen. (Although I may need to do some more investigation as to this, especially for collection views.)
UICollectionView:(选项:no prefetching
、prefetch cells
或 prefetch cells and data
)
- 默认预取单元格.换句话说,它将为不会立即显示的单元格调用
cellForItemAtIndexPath
. - 仅当用户在集合视图上向上或向下滚动时才会开始预取单元格.换句话说,当视图被加载时,您将获得 8 次对
cellForItemAtIndexPath
的调用.只有当用户向下滚动时,它才会开始询问不可见的单元格(例如,如果您向下滚动以显示 2-10,它可能会询问 11-14). - 当预取的、不可见的单元格出现在屏幕上时,它不会再次调用
cellForItemAtIndexPath
.它会假设您第一次执行的实例化仍然有效. - 您可以选择使用
prefetchDataSource
预取 数据. prefetchDataSource
只对初始加载有用.例如,在上述相同的场景中,当显示前 8 个单元格时,它可能会触发对单元格 9-14 的数据的预取.但是,一旦调用了这个初始方法,之后就没有用了.这是因为cellForItemAtIndexPath
将在每次调用prefetchItemsAt
后立即被调用.例如,您会立即获得prefetchItemsAt:[14, 15]
,然后是cellForItemAt:14
、cellForItemAt:15
.- 您可以通过设置
isPrefetchingEnabled = false
来退出所有预取行为.这意味着您不能使 UICollectionView 的行为类似于具有prefetchDataSource
的 UITableView.或者,换句话说,你不能只拥有一个 UICollectionViewprefetch data
.
- Prefetches cells by default. In other words, it will call
cellForItemAtIndexPath
for cells that aren't going to be immediately displayed. - The prefetching of cells only begins when the user scrolls up or down on the collection view. In other words, you will get exactly 8 calls to
cellForItemAtIndexPath
when the view is loaded. Only once the user scrolls down will it start asking for non-visible cells (e.g. if you scrolled down to show 2-10, it might ask for 11-14). - When the prefetched, non-visible cell comes on screen, it's not going to call
cellForItemAtIndexPath
again. It's going to assume that instantiation you did the first time is still valid. - You can opt-in to prefetching data by using the
prefetchDataSource
. - The
prefetchDataSource
turns out to be only useful for the initial load. In the same scenario above, when the first 8 cells are displayed, it may fire off a prefetching of data for cells 9-14, for example. However, once this initial method is called, it's useless thereafter. This is becausecellForItemAtIndexPath
is going to be called immediately after each call toprefetchItemsAt
. For example, you'll getprefetchItemsAt:[14, 15]
immediately followed bycellForItemAt:14
,cellForItemAt:15
. - You can opt-out of all prefetching behavior by setting
isPrefetchingEnabled = false
. This means you can't make a UICollectionView behave similarly to a UITableView with aprefetchDataSource
. Or, in other words, you can not have a UICollectionViewprefetch data
only.
两者都:
visibleCells
、indexPathsForVisibleRows
和cellForItemAtIndexPath
完全按照他们的说法:它们只处理 visible 单元格.在我们相同的场景中,如果我们加载了 20 个单元格,但屏幕上只有 8 个单元格可见.所有这 3 种方法都只会报告屏幕上的 8 个单元格.
visibleCells
,indexPathsForVisibleRows
, andcellForItemAtIndexPath
do exactly as they say: they only deal with visible cells. In our same scenario, if we have 20 cells loaded, but only 8 are visible on screen. All 3 of these methods will only report about the 8 on-screen cells.
那么这是什么意思呢?
- 如果您使用的是 UITableView,则可以按原样使用它,而不必担心已加载单元格与可见单元格之间的差异.它们总是等价的.
- 另一方面,对于 UICollectionView,如果您关心这种差异,则需要做一些簿记以跟踪已加载的不可见单元格与可见单元格.您可以通过查看数据源上的一些方法和委托方法(例如 willDisplayCell、didEndDisplayingCell)来做到这一点.
这篇关于在 UITableView 或 UICollectionView 上加载与可见单元格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!