如何检查indexPath是否有效,从而避免“尝试滚动到无效索引路径”错误?

如何检查indexPath是否有效?

我想滚动到索引路径,但如果我的集合视图的子视图未完成加载,我有时会收到错误。

你可以检查一下

- numberOfSections - numberOfItemsInSection: 

您的UICollection​View​Data​Source以查看您的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]

使用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) } 

也许这就是你要找的东西?

- (UICollectionViewCell *)cellForItemAtIndexPath:(NSIndexPath *)indexPath

返回值:相应索引路径中的单元格对象,如果单元格不可见或indexPath超出范围,则为nil。