Comment puis-je vérifier si un indexPath est valide ou non?
Je souhaite faire défiler jusqu'à un chemin d'index, mais je reçois parfois une erreur si le chargement des sous-vues de ma collection est terminé.
Tu pourrais vérifier
- numberOfSections
- numberOfItemsInSection:
de votre UICollectionViewDataSource
pour voir si votre indexPath est valide.
Une solution plus concise?
func indexPathIsValid(indexPath: NSIndexPath) -> Bool {
if indexPath.section >= numberOfSectionsInCollectionView(collectionView) {
return false
}
if indexPath.row >= collectionView.numberOfItemsInSection(indexPath.section) {
return false
}
return true
}
ou plus compact, mais moins lisible ...
func indexPathIsValid(indexPath: NSIndexPath) -> Bool {
return indexPath.section < numberOfSectionsInCollectionView(collectionView) && indexPath.row < collectionView.numberOfItemsInSection(indexPath.section)
}
La réponse de @ ABakerSmith est proche, mais pas tout à fait raison.
La réponse dépend de votre modèle.
Si vous avez une vue de collection à plusieurs sections (ou une vue de table - le même problème), il est assez courant d'utiliser un tableau de tableaux pour sauvegarder vos données.
Le tableau externe contient vos sections et chaque tableau interne contient les lignes de cette section.
Donc, vous pourriez avoir quelque chose comme ça:
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
Dans ce cas, lorsqu'un indexPath vous est présenté, vous devez interroger votre objet modèle (myTableViewData, dans l'exemple ci-dessus).
Le code pourrait ressembler à ceci:
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 a une tournure intéressante: Demander la source de données. De cette façon, vous pouvez écrire une solution qui fonctionne quel que soit le modèle de données. Son code est proche, mais pas encore tout à fait correct. Ça devrait vraiment être ça:
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
}
Voici un extrait de Swift 4 que j'ai écrit et que j'utilise depuis longtemps. Il vous permet de faire défiler jusqu'à IndexPath uniquement s'il est disponible ou - émettez une erreur si IndexPath n'est pas disponible pour vous permettre de contrôler ce que vous voulez faire dans cette situation.
Découvrez le code ici:
https://Gist.github.com/freak4pc/0f244f41a5379f001571809197e72b90
Il vous permet de faire soit:
myCollectionView.scrollToItemIfAvailable(at: indexPath, at: .top, animated: true)
Ou
myCollectionView.scrollToItemOrThrow(at: indexPath, at: .top, animated: true)
Ce dernier lancerait quelque chose comme:
expression unexpectedly raised an error: IndexPath [0, 2000] is not available. The last available IndexPath is [0, 36]
Utilisation de l'extension Swift:
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)
}
Si vous essayez de définir l'état d'une cellule dans la vue de collection sans savoir si le chemin d'index est valide ou non, vous pouvez essayer de sauvegarder les index des cellules avec un état spécial et de définir l'état des cellules lors du chargement.