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

web*_*ets 35 nsindexpath ios uicollectionview swift

如何检查indexPath是否有效?

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

muf*_*ffe 34

你可以检查一下

- numberOfSections
- numberOfItemsInSection: 
Run Code Online (Sandbox Code Playgroud)

你的UICollection?View?Data?Source,看看你的indexPath是一个有效的.


And*_*lla 22

更简洁的解决方案?

func indexPathIsValid(indexPath: NSIndexPath) -> Bool {
    if indexPath.section >= numberOfSectionsInCollectionView(collectionView) {
        return false
    }
    if indexPath.row >= collectionView.numberOfItemsInSection(indexPath.section) {
        return false
    }
    return true
}
Run Code Online (Sandbox Code Playgroud)

或更紧凑,但不太可读......

func indexPathIsValid(indexPath: NSIndexPath) -> Bool {
    return indexPath.section < numberOfSectionsInCollectionView(collectionView) && indexPath.row < collectionView.numberOfItemsInSection(indexPath.section)
}
Run Code Online (Sandbox Code Playgroud)


Dun*_*n C 12

@ 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
Run Code Online (Sandbox Code Playgroud)

在这种情况下,当使用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
}
Run Code Online (Sandbox Code Playgroud)

编辑:

@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
}
Run Code Online (Sandbox Code Playgroud)


Sha*_*ali 6

这是我写的Swift 4片段,已经使用了一段时间。它可以让您仅在索引路径可用时滚动到它,或者-在索引路径不可用时抛出一个错误,以让您控制在这种情况下要执行的操作。

看看这里的代码:

https://gist.github.com/freak4pc/0f244f41a5379f001571809197e72b90

它可以让你可以:

myCollectionView.scrollToItemIfAvailable(at: indexPath, at: .top, animated: true)
Run Code Online (Sandbox Code Playgroud)

要么

myCollectionView.scrollToItemOrThrow(at: indexPath, at: .top, animated: true)
Run Code Online (Sandbox Code Playgroud)

后者会抛出这样的:

expression unexpectedly raised an error: IndexPath [0, 2000] is not available. The last available IndexPath is [0, 36]


Ash*_*hok 6

使用快速扩展:

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)
}
Run Code Online (Sandbox Code Playgroud)