Log139 Log139 - 3 months ago 35
iOS Question

UICollectionView cell selection and cell reuse

Upon cell selection, I want to handle changing the cell appearance. I figured the delegate method

collectionView:didSelectItemAtIndexPath:
&
collectionView:didDeselectItemAtIndexPath:
is where I should edit the cell.

-(void)collectionView:(UICollectionView *)collectionView
didSelectItemAtIndexPath:(NSIndexPath *)indexPath {

DatasetCell *datasetCell =
(DatasetCell *)[collectionView cellForItemAtIndexPath:indexPath];

[datasetCell replaceHeaderGradientWith:[UIColor skyBlueHeaderGradient]];
datasetCell.backgroundColor = [UIColor skyBlueColor];
}


and



-(void)collectionView:(UICollectionView *)collectionView
didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {

DatasetCell *datasetCell =
(DatasetCell *)[collectionView cellForItemAtIndexPath:indexPath];

[datasetCell replaceHeaderGradientWith:[UIColor grayGradient]];
datasetCell.backgroundColor = [UIColor myDarkGrayColor];
}


This works fine, except when the cell gets reused. If I select cell at index (0, 0), it changes the appearance but when I scroll down, there is another cell in the selected state.

I believe I should use the
UICollectionViewCell
method
-(void)prepareForReuse
to prep the cell for resuse (ie, set the cell appearance to non selected state) but its giving me difficulties.

-(void)prepareForReuse {
if ( self.selected ) {
[self replaceHeaderGradientWith:[UIColor skyBlueHeaderGradient]];
self.backgroundColor = [UIColor skyBlueColor];
} else {
[self replaceHeaderGradientWith:[UIColor grayGradient]];
self.backgroundColor = [UIColor myDarkGrayColor];
}
}


When I scroll back to the top, the cell at index (0, 0) is in the deselected state.

When I just used the cell.backgroundView property, to prevent this from happening was to:

-(void)prepareForReuse {
self.selected = FALSE;
}


and the selection state worked as intended.

Any ideas?

Answer

Your observation is correct. This behavior is happening due to the reuse of cells. But you dont have to do any thing with the prepareForReuse. Instead do your check in cellForItem and set the properties accordingly. Some thing like..

 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cvCell" forIndexPath:indexPath];


if (cell.selected) {
     cell.backgroundColor = [UIColor blueColor]; // highlight selection 
}
else
{
     cell.backgroundColor = [UIColor redColor]; // Default color
}
return cell;
}

-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath  {

    UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath];
    datasetCell.backgroundColor = [UIColor blueColor]; // highlight selection
 }  

 -(void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {

UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath]; 
datasetCell.backgroundColor = [UIColor redColor]; // Default color
}