28

I have a function that updates existing UICollectionView. The UICollectionView is created, I can see it, but when I want to access its cells to update it, they are nil.

-(void)finishExam{

    for (int i = 0; i < [self.questionsOverviewCollection numberOfItemsInSection:0]; i++) {

        NSLog(@"self.questionsOverviewCollection - %@",self.questionsOverviewCollection);
        NSLog(@"cell - %@",[self.questionsOverviewCollection cellForItemAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]]);
        NSLog(@"overviewCell - %@",(OverviewCell*)[self.questionsOverviewCollection cellForItemAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]]);
        NSLog(@"numOfCells - %d", [self.questionsOverviewCollection numberOfItemsInSection:0]);

        OverviewCell *cell = (OverviewCell*)[self.questionsOverviewCollection cellForItemAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
            [cell finishExam];
    }
}


- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{

    OverviewCell *cell = (OverviewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];

    [cell someSetUp];

    return cell;
}

Log:

self.questionsOverviewCollection - <UICollectionView: 0xa1abc00; frame = (14 219; 217 441); clipsToBounds = YES; opaque = NO; autoresize = W+H; gestureRecognizers = <NSArray: 0xe0617a0>; layer = <CALayer: 0xe0bbb00>; contentOffset: {0, 0}> collection view layout: <UICollectionViewFlowLayout: 0xe0cc3f0>
cell - (null)
overviewCell - (null)
numOfCells - 30
Luda
  • 7,282
  • 12
  • 79
  • 139
  • You are getting all cell null or you get some cell and after that u get null? – CRDave Apr 04 '14 at 11:45
  • Though the answers here work, if you can, it's better to call `[cell finishExam]` directly on your data model instead of proxing through the `collectionView`. See my comment on Paul S.'s answer. In most cases, you should be able to get cell layout information from the `collectionViewLayout` property, and model specific functionality like `- finishExam` should be available on your model, or configured when the cell is dequeued. – nteissler Dec 16 '19 at 16:17

2 Answers2

54

From the UICollectionView docs (emphasis my own)

Return Value
The cell object at the corresponding index path or nil if the cell is not visible or indexPath is out of range.

You should update your underlying model, which provides the data to the views.

Paul.s
  • 38,494
  • 5
  • 70
  • 88
  • 10
    This worked for me, but in addition to reloading the data with [view reloadData], I also had to [view layoutIfNeeded] as per http://stackoverflow.com/a/21480786/1388195 – zyzof Sep 24 '14 at 05:24
  • 28
    Calling [collectionView layoutIfNeeded] worked for me to acquire the cell after calling [collectionView reloadData]. Thanks @zyzof – Richard McCluskey Feb 18 '16 at 22:49
  • 3
    Thanks all for the layoutIfNeeded!!! :D Just wondering, does anyone know why though? Cause in my case the cell has been visible the entire time. – Happiehappie Jun 14 '16 at 08:59
  • 1
    Hey @RichardMcCluskey, do you know why we have to call this? I notice that all the UICollectionViews are rendered properly but indeed, without this line of call `cellForItemAtIndexPath` is returning `nil` all the time! – Yuchen Feb 02 '17 at 19:26
  • 1
    Hey @zyzof, you should totally post your suggestion as a separate answer!! That works great for me! – Yuchen Feb 03 '17 at 14:53
  • If you 'drag' the cell outside the collection view's frame, it will not be visible. – David Nov 19 '17 at 15:41
  • Calling `layoutIfNeeded` worked for me. However, I didn't like the explicit need to call that. In my specific use case, I was subclassing `UICollectionViewFlowLayout` and calling `collectionView.cellForItemAt` in my `layoutAttributesForItem(at indexPath:)` implementation. I was able to get all the information for cell layout I needed from `super.layoutAttributesForItem(at indexPath: IndexPath)`. – nteissler Dec 16 '19 at 16:15
  • On iOS 10 and above `nil` from `UICollectionView`'s `cellForItem(at indexPath)` can be caused by prefetching, see https://stackoverflow.com/questions/40322995/uicollectionview-cellforitematindexpath-returns-null-in-ios-10-only-works-fine – jedwidz Jan 04 '21 at 16:06
  • Documentation is not accurate. I fetched the index I'm trying to use in `cellForItem(at:)` directly from my data source. The collection view is just out of sync. `layoutIfNeeded` fixed for me. – henrique Mar 15 '23 at 18:30
19

Try this:

[collectionView reloadData];
[collectionView layoutIfNeeded];
zyzof
  • 3,415
  • 1
  • 25
  • 21