Получение загруженных vs видимых ячеек в UITableView или UICollectionView

С введением iOS 10 кажется, что у нас будет prefetching включен по умолчанию в UITableView и UICollectionViews. Это означает, что ячейки, которые не отображаются на экране, будут выбраны, прежде чем пользователь их увидит.

Вот некоторые релевантные методы:

UITableView:

  • cellForRowAtIndexPath:: возвращает "nil, если ячейка не видна."
  • visibleCells: каждый элемент представляет "видимую ячейку в представлении таблицы".
  • indexPathsForVisibleRows: каждый элемент представляет "видимую строку в представлении таблицы".

UICollectionView:

  • visibleCells: "возвращает полный список видимых ячеек, отображаемых в виде коллекции."
  • indexPathsForVisibleItems: каждый элемент представляет "видимую ячейку в представлении коллекции".
  • cellForItemAtIndexPath:: возвращает "nil, если ячейка не видна."

Все это конкретно упоминает "видимые" в своих описаниях. С введением предварительной выборки в iOS 10, как бы я мог различать предварительно выбранную ячейку против той, которая в настоящее время видима?

Другими словами:

  • Как получить все видимые ячейки?
  • Как получить все загруженные ячейки?

Не похоже, что есть какие-либо новые API-интерфейсы для UITableView или UICollectionView, которые могут помочь в этом.

Ответы

Ответ 1

TL; DR

  • Возьмите visible в именах функций буквально.
  • UITableView ведет себя так же, как в iOS 9.
  • Вам нужно будет сделать некоторую бухгалтерскую отчетность, если вы хотите обрабатывать загруженные и видимые ячейки по-разному в UICollectionView на iOS 10.

UITableView и UICollectionView выглядят очень по-разному, когда дело доходит до предварительной выборки.

Прежде всего следует заметить, что существует разница между предварительной выборкой ячеек и предварительной выборкой данных:

  • Предварительная выборка ячеек относится к вызову cellForRowAtIndexPath, прежде чем ячейка будет фактически отображаться на экране. Это позволяет сценарий, в котором у вас есть ячейки, которые находятся вне экрана, но все еще загружены.
  • Предварительная выборка данных относится к методам prefetchDataSource, которые сообщают вам о indexPaths, которые будут отображаться на экране. У вас нет ссылки на ячейку при вызове этого метода, и вы не возвращаете ячейку при вызове этого метода. Вместо этого этот метод должен делать такие вещи, как отключение сетевого запроса для загрузки изображения, которое будет отображаться в ячейке.

Примечание. Во всех этих сценариях представьте, что в любой момент времени могут отображаться 8 ячеек.

UITableView: (опции: no prefetching или prefetch data)

  • Не требует предварительной выборки ячеек. Другими словами, он никогда не вызовет cellForRowAtIndexPath на indexPath, который не отображается.
  • Таким образом, в UITableView нет свойства isPrefetchingEnabled.
  • Вы можете выбрать предварительную выборку данных с помощью prefetchDataSource.
  • Обратите внимание, что хотя представление таблицы выглядит менее агрессивным при повторном использовании ячеек, оно по-прежнему вызывает вызов cellForItemAtIndexPath, когда повторно используемая ячейка возвращается на экран. (Хотя мне, возможно, потребуется сделать еще несколько исследований по этому поводу, особенно для просмотров коллекции.)

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 вести себя аналогично UITableView с помощью prefetchDataSource. Или, другими словами, вы не можете использовать только UICollectionView prefetch data.

Для обоих:

  • visibleCells, indexPathsForVisibleRows и cellForItemAtIndexPath выполняют именно так, как они говорят: они касаются только видимых ячеек. В том же сценарии, если у нас есть 20 ячеек, но на экране видны только 8. Все 3 из этих методов будут сообщать только о 8 экранных ячейках.

И что это значит?

  • Если вы используете UITableView, вы можете использовать его как есть и никогда не должны беспокоиться о различии между загружаемыми и видимыми ячейками. Они всегда эквивалентны.
  • Для UICollectionView, с другой стороны, вам понадобится сделать некоторые бухгалтерские книги, чтобы отслеживать загруженные, невидимые ячейки или видимые ячейки, если вам небезразлична эта разница. Вы можете сделать это, просмотрев некоторые из методов в источнике данных и делегировать методы (например, willDisplayCell, didEndDisplayingCell).