ios 如何检查 indexPath 是否有效,从而避免“尝试滚动到无效索引路径”错误?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29516638/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I check if an indexPath is valid, thus avoiding an "attempt to scroll to invalid index path" error?
提问by webmagnets
How can I check to see whether an indexPath
is valid or not?
如何检查 a 是否indexPath
有效?
I want to scroll to an indexPath
, but I sometimes get an error if my UICollectionView
subviews aren't finished loading.
我想滚动到indexPath
,但如果我的UICollectionView
子视图没有完成加载,我有时会收到错误消息。
采纳答案by muffe
You could check
你可以检查
- numberOfSections
- numberOfItemsInSection:
of your UICollection?View?Data?Source
to see if your indexPath is a valid one.
你的UICollection?View?Data?Source
,看看你的indexPath是一个有效的。
E.g.
例如
extension UICollectionView {
func isValid(indexPath: IndexPath) -> Bool {
guard indexPath.section < numberOfSections,
indexPath.row < numberOfItems(inSection: indexPath.section)
else { return false }
return true
}
}
回答by Andres Canella
A more concise solution?
更简洁的解决方案?
func indexPathIsValid(indexPath: NSIndexPath) -> Bool {
if indexPath.section >= numberOfSectionsInCollectionView(collectionView) {
return false
}
if indexPath.row >= collectionView.numberOfItemsInSection(indexPath.section) {
return false
}
return true
}
or more compact, but less readable...
或更紧凑,但可读性较差......
func indexPathIsValid(indexPath: NSIndexPath) -> Bool {
return indexPath.section < numberOfSectionsInCollectionView(collectionView) && indexPath.row < collectionView.numberOfItemsInSection(indexPath.section)
}
回答by Duncan C
@ABakerSmith's answer is close, but not quite right.
@ABakerSmith 的回答很接近,但不太正确。
The answer depends on your model.
答案取决于您的型号。
If you have a multi-section collection view (or table view for that matter - same issue) then it's pretty common to use an array of arrays to save your data.
如果你有一个多部分的集合视图(或表视图——同样的问题),那么使用数组数组来保存数据是很常见的。
The outer array contains your sections, and each inner array contains the rows for that section.
外部数组包含您的部分,每个内部数组包含该部分的行。
So you might have something like this:
所以你可能有这样的事情:
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
In that case, when presented with an indexPath, you'd need to interrogate your model object (myTableViewData, in the above example)
在这种情况下,当出现 indexPath 时,您需要询问您的模型对象(myTableViewData,在上面的示例中)
The code might look like this:
代码可能如下所示:
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
}
EDIT:
编辑:
@ABakerSmith has an interesting twist: Asking the data source. That way you can write a solution that works regardless of the data model. His code is close, but still not quite right. It should really be this:
@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
}
回答by Ashok
Using swift extension:
使用快速扩展:
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)
}
回答by Shai Mishali
Here's a Swift 4 snippet I wrote and have been using for a while. It lets you either scroll to an IndexPath only if it's available, or - throw an error if the IndexPath is not available, to let you control what you want to do in this situation.
这是我编写并使用了一段时间的 Swift 4 代码段。它允许您仅在 IndexPath 可用时滚动到它,或者 - 如果 IndexPath 不可用则抛出错误,让您控制在这种情况下要执行的操作。
Check out the code here:
在这里查看代码:
https://gist.github.com/freak4pc/0f244f41a5379f001571809197e72b90
https://gist.github.com/freak4pc/0f244f41a5379f001571809197e72b90
It lets you do either:
它可以让您执行以下任一操作:
myCollectionView.scrollToItemIfAvailable(at: indexPath, at: .top, animated: true)
Or
或者
myCollectionView.scrollToItemOrThrow(at: indexPath, at: .top, animated: true)
The latter would throw something like:
后者会抛出类似的东西:
expression unexpectedly raised an error: IndexPath [0, 2000] is not available. The last available IndexPath is [0, 36]
expression unexpectedly raised an error: IndexPath [0, 2000] is not available. The last available IndexPath is [0, 36]
回答by Denis Kutlubaev
Objective C version:
目标 C 版本:
- (BOOL)indexPathIsValid:(NSIndexPath *)indexPath
{
return indexPath.section < [self.collectionView numberOfSections] && indexPath.row < [self.collectionView numberOfItemsInSection:indexPath.section];
}
回答by Lloyd Keijzer
You should check the validation of the index paths that will be appended with the data source(future state) and the deletion of index paths with the current existing ones(present state).
您应该检查将附加到数据源(未来状态)的索引路径的验证以及使用当前现有的索引路径(当前状态)的删除。
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
}
usage:
用法:
// insert
tableView.insertRows(at: indexPaths.filter({ tableView.isValid(indexPath: true or false
, inDataSource: true) }), with: .top)
// remove
tableView.deleteRows(at: indexPaths.filter({ tableView.isValid(indexPath: ##代码##) }), with: .top)
output:
输出:
##代码##回答by carrotzoe
If you are trying to set the state of a cell in the collection view without knowing whether the index path is valid or not, you could try saving the indices for cells with a special state, and set the state of the cells while loading them.
如果您在不知道索引路径是否有效的情况下尝试在集合视图中设置单元格的状态,您可以尝试保存具有特殊状态的单元格的索引,并在加载它们时设置单元格的状态。
回答by Thorory
Perhaps this is what you're looking for?
也许这就是你要找的?
- (UICollectionViewCell *)cellForItemAtIndexPath:(NSIndexPath *)indexPath
- (UICollectionViewCell *)cellForItemAtIndexPath:(NSIndexPath *)indexPath
Return Value: The cell object at the corresponding index path or nil if the cell is not visible or indexPath is out of range.
返回值:对应索引路径的单元格对象,如果单元格不可见或 indexPath 超出范围,则为 nil。