在强制滚动后,cellForItemAtIndexPath返回nil以使其可见

时间:2014-01-30 23:13:40

标签: ios objective-c ios7 uicollectionview

所以我试着编写一些代码来将集合视图滚动到某个索引,然后拉出对单元格的引用并做一些逻辑。但是,我注意到如果在滚动之前该单元格当前不可见,cellForItemAtIndexPath调用将返回nil,导致其余逻辑失败。

[_myView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:index 
                                                     inSection:0] 
                atScrollPosition:UICollectionViewScrollPositionTop
                        animated:NO];

//Tried with and without this line, thinking maybe this would trigger a redraw
[_myView reloadData];

//returns nil if cell was off-screen before scroll
UICollectionViewCell *cell = 
  [_myView cellForItemAtIndexPath:
    [NSIndexPath indexPathForItem:index inSection:0]];

是否还有其他一些方法需要调用才能使cellForItemAtIndexPath为一个单元格返回一些内容,这些单元格由于前面的滚动而突然出现?

4 个答案:

答案 0 :(得分:21)

我现在想出了一个解决方案。如果我在调用reloadData后立即调用[myView layoutIfNeeded],但在我尝试检索单元格之前,一切正常。现在所有单元都被缓存,因此访问速度很快,但是如果我必须从Web或内部数据库加载,这可能会给我带来糟糕的性能,但我们会看到。

答案 1 :(得分:17)

如果您想访问该单元格并在屏幕上显示该单元格:

NSIndexPath *indexPath = ...;

[collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically | UICollectionViewScrollPositionCenteredHorizontally animated:NO];

UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];

if(cell == nil) {
    [collectionView layoutIfNeeded];
    cell = [collectionView cellForItemAtIndexPath:indexPath];
}

if(cell == nil) {
    [collectionView reloadData];
    [collectionView layoutIfNeeded];
    cell = [collectionView cellForItemAtIndexPath:indexPath];
}

我很少进入第二个if语句,但有两个这样的后退非常有用。

答案 2 :(得分:12)

根据你的评论,这听起来像你最终的细胞框架。在不依赖单元格存在的情况下执行此操作的方法是询问集合视图的布局:

NSIndexPath *indexPath = ...;
UICollectionViewLayoutAttributes *pose = [self.collectionView.collectionViewLayout layoutAttributesForItemAtIndexPath:indexPath];
CGRect frame = pose.frame;

答案 3 :(得分:1)

hfossli的解决方案对我有用,所以我在下面提供了一个Swift版本。在我的情况下,我无法获得对自定义UICollectionViewCell的引用,可能是因为它不可见。我尝试了很多东西,但正如Shaybc所说,这是唯一可行的解​​决方案。

斯威夫特3:

man verify

用法:

  func getCell(_ indexPath: IndexPath) -> CustCell? {
    cView.scrollToItem(at: indexPath, at: UICollectionViewScrollPosition.centeredHorizontally, animated: false)
    var cell = cView.cellForItem(at: indexPath) as? CustCell
    if cell == nil {
      cView.layoutIfNeeded()
      cell = cView.cellForItem(at: indexPath) as? CustCell
    }
    if cell == nil {
      cView.reloadData()
      cView.layoutIfNeeded()
      cell = cView.cellForItem(at: indexPath) as? CustCell
    }
    return cell
  }