Как я могу проверить, является ли indexPath
действительным или нет?
Я хочу перейти к indexPath
, но иногда я получаю сообщение об ошибке, если мои UICollectionView
не завершают загрузку.
Как я могу проверить, является ли indexPath
действительным или нет?
Я хочу перейти к indexPath
, но иногда я получаю сообщение об ошибке, если мои UICollectionView
не завершают загрузку.
Вы можете проверить
- numberOfSections
- numberOfItemsInSection:
вашего UICollectionViewDataSource
, чтобы узнать, является ли ваш indexPath допустимым.
Более сжатое решение?
func indexPathIsValid(indexPath: NSIndexPath) -> Bool {
if indexPath.section >= numberOfSectionsInCollectionView(collectionView) {
return false
}
if indexPath.row >= collectionView.numberOfItemsInSection(indexPath.section) {
return false
}
return true
}
или более компактный, но менее читаемый...
func indexPathIsValid(indexPath: NSIndexPath) -> Bool {
return indexPath.section < numberOfSectionsInCollectionView(collectionView) && indexPath.row < collectionView.numberOfItemsInSection(indexPath.section)
}
Ответ @ABakerSmith близок, но не совсем прав.
Ответ зависит от вашей модели.
Если у вас есть многосекторное представление коллекции (или табличное представление, в этом отношении - та же проблема), то довольно часто использовать массив массивов для сохранения ваших данных.
Внешний массив содержит ваши разделы, и каждый внутренний массив содержит строки для этого раздела.
Итак, у вас может быть что-то вроде этого:
struct TableViewData
{
//Dummy structure, replaced with whatever you might use instead
var heading: String
var subHead: String
var value: Int
}
typealias RowArray: [TableViewData]
typeAlias SectionArray: [RowArray]
var myTableViewData: SectionArray
В этом случае при представлении indexPath вам нужно будет опросить объект модели (myTableViewData, в приведенном выше примере)
Код может выглядеть так:
func indexPathIsValid(theIndexPath: NSIndexPath) -> Bool
{
let section = theIndexPath.section!
let row = theIndexPath.row!
if section > myTableViewData.count-1
{
return false
}
let aRow = myTableViewData[section]
return aRow.count < row
}
@ABakerSmith имеет интересный поворот: запрашивает источник данных. Таким образом, вы можете написать решение, которое работает независимо от модели данных. Его код близок, но все еще не совсем прав. Это должно быть действительно так:
func indexPathIsValid(indexPath: NSIndexPath) -> Bool
{
let section = indexPath.section!
let row = indexPath.row!
let lastSectionIndex =
numberOfSectionsInCollectionView(collectionView) - 1
//Make sure the specified section exists
if section > lastSectionIndex
{
return false
}
let rowCount = self.collectionView(
collectionView, numberOfItemsInSection: indexPath.section) - 1
return row <= rowCount
}
Вот фрагмент кода Swift 4, который я написал и какое-то время использовал. Он позволяет вам либо прокрутить IndexPath, только если он доступен, либо - выдать ошибку, если IndexPath недоступен, чтобы позволить вам контролировать то, что вы хотите сделать в этой ситуации.
Проверьте код здесь:
https://gist.github.com/freak4pc/0f244f41a5379f001571809197e72b90
Это позволяет вам сделать либо:
myCollectionView.scrollToItemIfAvailable(at: indexPath, at: .top, animated: true)
Или же
myCollectionView.scrollToItemOrThrow(at: indexPath, at: .top, animated: true)
Последний бросил бы что-то вроде:
expression unexpectedly raised an error: IndexPath [0, 2000] is not available. The last available IndexPath is [0, 36]
Используя быстрое расширение:
extension UICollectionView {
func validate(indexPath: IndexPath) -> Bool {
if indexPath.section >= numberOfSections {
return false
}
if indexPath.row >= numberOfItems(inSection: indexPath.section) {
return false
}
return true
}
}
// Usage
let indexPath = IndexPath(item: 10, section: 0)
if sampleCollectionView.validate(indexPath: indexPath) {
sampleCollectionView.scrollToItem(at: indexPath, at: UICollectionViewScrollPosition.centeredHorizontally, animated: true)
}
Если вы пытаетесь установить состояние ячейки в представлении коллекции, не зная, допустим ли путь индекса, вы можете попытаться сохранить индексы для ячеек с особым состоянием и установить состояние ячеек при их загрузке.
Версия C:
- (BOOL)indexPathIsValid:(NSIndexPath *)indexPath
{
return indexPath.section < [self.collectionView numberOfSections] && indexPath.row < [self.collectionView numberOfItemsInSection:indexPath.section];
}
Вы должны проверить правильность путей индекса, которые будут добавлены к источнику данных (будущее состояние), и удаление путей индекса с текущими существующими (текущее состояние).
extension UITableView {
func isValid(indexPath: IndexPath, inDataSource: Bool = false) -> Bool {
guard
let numberOfSections = inDataSource
? dataSource?.numberOfSections?(in: self)
: numberOfSections,
let numberOfRows = inDataSource
? dataSource?.tableView(self, numberOfRowsInSection: indexPath.section)
: numberOfRows(inSection: indexPath.section)
else {
preconditionFailure("There must be a datasource to validate an index path")
}
return indexPath.section < numberOfSections && indexPath.row < numberOfRows
}
использование:
// insert
tableView.insertRows(at: indexPaths.filter({ tableView.isValid(indexPath: $0, inDataSource: true) }), with: .top)
// remove
tableView.deleteRows(at: indexPaths.filter({ tableView.isValid(indexPath: $0) }), with: .top)
выход:
true or false
Возможно, это то, что вы ищете?
- (UICollectionViewCell *)cellForItemAtIndexPath:(NSIndexPath *)indexPath
Возвращаемое значение: Объект ячейки по соответствующему пути индекса или nil, если ячейка не видна, или indexPath выходит за допустимые пределы.