Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UICollectionView showing wrong cells after scrolling - dequeue issue?

I have a UICollectionView within a UIViewController. In the collectionView cellForItemAtIndexPath: method, it creates a series of custom cells based on the datasource. The custom cells in turn contain a UIView, subclassed to draw single PDF pages.

It's set up in such a way as to split a PDF file into its single pages, so cell 1 contains PDF page 1, cell 2 contains PDF page 2 and so on. So far so good, here's my problem:

When I scroll down, the UICollectionView starts displaying the wrong cells. For instance in a 34 page document, it shows cells/pages 1-16 in the correct order, but then starts displaying pages that seemed to have been dequeued further up, such as cell 1, cell 2, cell 4. I never get anywhere near cell/page 34.

I've seen similar behaviour from UITableView in the past, and believe it has something to do with the dequeueing of the cells, or a delegate method. Not quite sure - any help is appreciated.

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

//create custom cell
CustomCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellID" forIndexPath:indexPath];

//set file name (always the same; one PDF file)
cell.fileName = fileName;
cell.backgroundColor = [UIColor clearColor];

//set the title to the page number
cell.title = [NSString stringWithFormat:@"page %@", [countArray objectAtIndex:indexPath.row]];

//set the current page (which indicates which page to display) according to the pageCount
cell.currentPage = [[countArray objectAtIndex:indexPath.row] intValue];

return cell; }
like image 928
Johnny Rockex Avatar asked Oct 31 '12 17:10

Johnny Rockex


3 Answers

I've had similare issues. This is most likely because the reused cells do not redraw themselves. In your custom cell's content class (your PDF view), trigger redrawing if the frame is updated:

-(void)setFrame:(CGRect)frame {
    [super setFrame:frame];
    [self setNeedsDisplay]; // force drawRect:
}

This worked for me. In addition, if your cell size may change, set the autoresizing mask so that it fills space with

self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

during initialization.

like image 96
chris Avatar answered Nov 03 '22 02:11

chris


Fixed similar issue using prepareForReuse method

just add this method to your custom cell implementation

- (void)prepareForReuse {

     self.fileName = nil;
     self.title = nil;

     // add remaining properties 

}
like image 20
Asatur Galstyan Avatar answered Nov 03 '22 02:11

Asatur Galstyan


I fixed a similar issue in swift based on Asatur Galstyan's answer.

After associating a custom class to a cell in a storyboard the prepareForReuse() function can be overriden:

import UIKit

class SomeCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var exampleView: UIView!
    @IBOutlet weak var exampleLabel: UILabel!

    override func prepareForReuse(){
        super.prepareForReuse()
        exampleLabel.textColor = nil
        exampleView.backgroundColor = nil
        exampleView.layer.cornerRadius = 0
    }
}

There default implementation of prepareForReuse() does nothing (at least in iOS 10) but Apple recommends calling the the super.prepareForReuse() when overriding anyway.

like image 25
Neil Billingham Avatar answered Nov 03 '22 02:11

Neil Billingham