Objective-c – How to determine indexPath of currently visible UICollectionView cell

objective cuicollectionview

I want to display some cell-specific text, but I can’t extricate the visible cell from the collection view.

Most helpful ones were these:

how to access from UICollectionViewCell the indexPath of the Cell in UICollectionView

detecting when an iOS UICollectionCell is going off screen

A lower collection view (self addSubview) contains possible items. An upper one (self addSubview) contains selections from the lower. The user presses a button (self addSubview again), the lower view scrolls off to oblivion and the upper one expands such that one cell fills the screen. All the array-building and displaying works fine. No *.nibs.

What doesn’t work is figuring out which cell the app is presenting to the user.

TRY #1: First I tried populating the UILabel in parallel with normal ops. Press the button and cellForItemAtIndexPath:

if (cv.tag == UPPER_CV_TAG) {
    UICollectionViewLayoutAttributes *itemAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    NSIndexPath *tempIndexPath;
tempIndexPath = itemAttributes.indexPath;
NSLog(@"cellForItem indexPath %@",indexPath);
NSLog(@"layout indexPath %@",tempIndexPath);
}

responds as you’d expect:

cellForItem indexPath <blah blah> 2 indexes [0, 0]
layout indexPath < > 2 indexes [0, 0]

cellForItem indexPath < > 2 indexes [0, 1]
layout indexPath < > 2 indexes [0, 1]

cellForItem indexPath < > 2 indexes [0, 2]
layout indexPath < > 2 indexes [0, 2]

When the gyrations conclude, Cell 0 correctly occupies center stage. Unfortunately, so does the description for cell 2. Scroll left / right, cells change accordingly, the corresponding text does not. It remains constant: that which maps to cell 2.

Obviously I’m passing the wrong index to the description array.

TRY #2: OK, fine. I’ll interrogate a point I know the currently visible cell occupies and reason backward from that.

CGPoint p = CGPointMake(512, 456);
NSIndexPath *theCellsIndexPath = [self.upper_collectionView indexPathForItemAtPoint:p];
NSLog(@"theCellsIndexPath=%d",theCellsIndexPath.item);

No cigar:

cellForItem indexPath < > 2 indexes [0, 0]
theCellsIndexPath=0

cellForItem indexPath < > 2 indexes [0, 1]
theCellsIndexPath=0

cellForItem indexPath < > 2 indexes [0, 2]
theCellsIndexPath=0

No change from “0” when I change 512,456 to other likely points. No change from “0” when I use layoutAttributes to determine where in the view the cell lies, just in case. Nope, that cell is a really, really big target. I’m not missing it.

TRY #3: Maybe I’m working too hard. I’ll trap the goings-on inside

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath  {
}

and roll with that.

Nope. It never gets called.

TRY #4: Since I don’t know the indexPath of the single cell on the screen (but the collectionView does) I suppose I could iterate through all the cells with didEndDisplayingCell until I hit “Bingo!” That’s crude and indicative of programmer error.

I’m glad the collectionView logic buffers three cells. Probably improves user experience or something. But where it ends up – on 0 – is not where my array index last knew it was – at 2.

What part of the docs didn’t I read?

Best Answer

What part of the docs didn’t I read?

UICollectionView has a method called indexPathsForVisibleItems . Make sure you read it through to see what else you can use from the API.

Related Topic