ios - how - uicollectionview header swift
¿Cómo puedo verificar si una indexPath es válida, evitando así un error de "intento de desplazamiento a una ruta de índice no válida"? (7)
¿Cómo puedo verificar si una indexPath es válida o no?
Quiero desplazarme a una ruta de índice, pero a veces me sale un error si las subvistas de mi vista de colección no han terminado de cargarse.
¿Una solución más concisa?
func indexPathIsValid(indexPath: NSIndexPath) -> Bool {
if indexPath.section >= numberOfSectionsInCollectionView(collectionView) {
return false
}
if indexPath.row >= collectionView.numberOfItemsInSection(indexPath.section) {
return false
}
return true
}
O más compacto, pero menos legible ...
func indexPathIsValid(indexPath: NSIndexPath) -> Bool {
return indexPath.section < numberOfSectionsInCollectionView(collectionView) && indexPath.row < collectionView.numberOfItemsInSection(indexPath.section)
}
Aquí hay un fragmento de Swift 4 que escribí y he estado usando por un tiempo. Le permite desplazarse a un IndexPath solo si está disponible, o - lanzar un error si el IndexPath no está disponible, para permitirle controlar lo que quiere hacer en esta situación.
Echa un vistazo al código aquí:
https://gist.github.com/freak4pc/0f244f41a5379f001571809197e72b90
Te permite hacer ya sea:
myCollectionView.scrollToItemIfAvailable(at: indexPath, at: .top, animated: true)
O
myCollectionView.scrollToItemOrThrow(at: indexPath, at: .top, animated: true)
Este último lanzaría algo como:
expression unexpectedly raised an error: IndexPath [0, 2000] is not available. The last available IndexPath is [0, 36]
La respuesta de @ ABakerSmith está cerca, pero no del todo bien.
La respuesta depende de tu modelo.
Si tiene una vista de colección de varias secciones (o vista de tabla para ese asunto, el mismo problema), es bastante común usar una matriz de matrices para guardar sus datos.
La matriz externa contiene sus secciones, y cada matriz interna contiene las filas de esa sección.
Entonces podrías tener algo como esto:
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
En ese caso, cuando se le presente una indexPath, deberá interrogar a su objeto modelo (myTableViewData, en el ejemplo anterior)
El código podría verse así:
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
}
EDITAR:
@ABakerSmith tiene un giro interesante: pedir la fuente de datos. De esa manera, puede escribir una solución que funcione independientemente del modelo de datos. Su código está cerca, pero todavía no es del todo correcto. Realmente debería ser esto:
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
}
Quizás esto es lo que estás buscando?
- (UICollectionViewCell *)cellForItemAtIndexPath:(NSIndexPath *)indexPath
Valor de retorno: el objeto de celda en la ruta de índice correspondiente o nil si la celda no es visible o indexPath está fuera de rango.
Si está intentando establecer el estado de una celda en la vista de colección sin saber si la ruta del índice es válida o no, puede intentar guardar los índices de las celdas con un estado especial y establecer el estado de las celdas mientras las carga.
Usando la extensión 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)
}
Usted podría comprobar
- numberOfSections
- numberOfItemsInSection:
de su UICollectionViewDataSource
para ver si su indexPath es válida.