Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The old contents of a reused UICollectionViewCell are briefly displayed when reusing cells in a UICollectionView

I am using a UICollectionView to display a grid of pictures that are asynchronously loaded from URLs. My collection view uses reusable cells to display the UICollectionViewCells. Everything is displayed properly when cells are not reused, but when I scroll around a bit, the reused cells briefly flash the old contents before they begin their normal behavior.

Here is the implementation of the custom UICollectionViewController:

#import "MyCollectionViewViewController.h"
#import "MyCollectionViewCell.h"

@interface MyCollectionViewViewController ()    
@property (strong, nonatomic) NSArray *data;    
@end

@implementation MyCollectionViewViewController

@synthesize data = _data;

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.data = @[
        @"http://s3-ec.buzzfed.com/static/enhanced/webdr01/2013/1/18/12/enhanced-buzz-wide-851-1358529670-4.jpg",
        @"http://s3-ec.buzzfed.com/static/enhanced/webdr03/2013/1/18/11/enhanced-buzz-wide-26311-1358526816-5.jpg",
        @"http://s3-ec.buzzfed.com/static/enhanced/webdr03/2013/1/18/11/enhanced-buzz-wide-26311-1358527190-11.jpg",
        @"http://s3-ec.buzzfed.com/static/enhanced/webdr02/2013/1/18/11/enhanced-buzz-wide-7517-1358526694-11.jpg",
        @"http://s3-ec.buzzfed.com/static/enhanced/webdr03/2013/1/18/11/enhanced-buzz-wide-1965-1358527802-7.jpg",
        @"http://s3-ec.buzzfed.com/static/enhanced/webdr03/2013/1/18/11/enhanced-buzz-wide-2165-1358527708-14.jpg",
        @"http://s3-ec.buzzfed.com/static/enhanced/webdr03/2013/1/18/11/enhanced-buzz-wide-1965-1358527894-12.jpg",
        @"http://s3-ec.buzzfed.com/static/enhanced/webdr02/2013/1/18/12/enhanced-buzz-wide-15957-1358529198-18.jpg",
        @"http://s3-ec.buzzfed.com/static/enhanced/webdr02/2013/1/18/12/enhanced-buzz-wide-16520-1358528981-9.jpg",
        @"http://s3-ec.buzzfed.com/static/enhanced/webdr02/2013/1/18/12/enhanced-buzz-wide-16517-1358529292-5.jpg",
        @"http://s3-ec.buzzfed.com/static/enhanced/webdr01/2013/1/18/12/enhanced-buzz-wide-20349-1358529323-20.jpg",
        @"http://s3-ec.buzzfed.com/static/enhanced/webdr01/2013/1/18/12/enhanced-buzz-wide-32444-1358529959-9.jpg",
        @"http://s3-ec.buzzfed.com/static/enhanced/webdr01/2013/1/18/12/enhanced-buzz-wide-32343-1358530043-7.jpg",
        @"http://s3-ec.buzzfed.com/static/enhanced/webdr02/2013/1/18/12/enhanced-buzz-wide-23646-1358530321-2.jpg",
        @"http://s3-ec.buzzfed.com/static/enhanced/webdr01/2013/1/18/12/enhanced-buzz-wide-28223-1358530801-15.jpg",
        @"http://s3-ec.buzzfed.com/static/enhanced/webdr01/2013/1/18/12/enhanced-buzz-wide-32273-1358530695-16.jpg",
        @"http://s3-ec.buzzfed.com/static/enhanced/webdr01/2013/1/18/12/enhanced-buzz-wide-31288-1358531103-16.jpg"
    ];

    [self.collectionView registerNib:[UINib nibWithNibName:@"MyCollectionViewCell" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:@"myView"];
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    NSString *urlString = [self.data objectAtIndex:indexPath.item];

    MyCollectionViewCell *myView = [collectionView dequeueReusableCellWithReuseIdentifier:@"myView" forIndexPath:indexPath];
    myView.urlString = urlString;

    [myView setNeedsDisplay];

    return myView;
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    return CGSizeMake(150, 150);
}

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return 1;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return self.data.count;
}

@end

Here is the implementation of the custom UICollectionViewCell.

#import "MyCollectionViewCell.h"
#import <QuartzCore/QuartzCore.h>
#import <AVFoundation/AVFoundation.h>

@interface MyCollectionViewCell ()

@property (weak, nonatomic) IBOutlet UIImageView *imageView;

@end

@implementation MyCollectionViewCell

@synthesize urlString = _urlString;

+ (void)loadAsyncImageFromURL:(NSString *)urlString withCallback:(void (^)(UIImage *))callback {
    NSURL *url = [NSURL URLWithString:urlString];

    dispatch_queue_t downloadQueue = dispatch_queue_create("com.example.downloadqueue", NULL);
    dispatch_async(downloadQueue, ^{
        NSData * imageData = [NSData dataWithContentsOfURL:url];
        UIImage *image = [UIImage imageWithData:imageData];

        dispatch_async(dispatch_get_main_queue(), ^{
            callback(image);
        });
    });
}

-(void) fadeInView:(UIView *)view WithSecondDuration:(double)duration {
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    animation.beginTime = 0;
    animation.duration = duration;
    animation.fromValue = [NSNumber numberWithFloat:0.0f];
    animation.toValue = [NSNumber numberWithFloat:1.0f];
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeBoth;
    animation.additive = NO;
    [view.layer addAnimation:animation forKey:@"opacityIN"];
}

- (void) setUrlString:(NSString *)urlString {
    _urlString = urlString;

    self.imageView.image = nil;
    self.imageView.layer.opacity = 0;

    if (urlString) {
        [MyCollectionViewCell loadAsyncImageFromURL:urlString withCallback:^(UIImage *image) {
            self.imageView.image = image;
            [self fadeInView:self.imageView WithSecondDuration:.25];
        }];
    }
}


@end
like image 671
fixedpoint Avatar asked Apr 29 '13 22:04

fixedpoint


People also ask

What is a UICollectionView?

An object that manages an ordered collection of data items and presents them using customizable layouts.

How do I reuse a Collectionview cell?

If you're working entirely in code, you can register a UICollectionViewCell subclass for use with your collection view, so that new cells are dequeued and re-use automatically by the system. If a cell doesn't already exist that can be re-used, a new one will be created automatically.

How to use uicollectionviewcell as-is or subclass?

You can use UICollectionViewCell as-is or subclass it to add additional properties and methods. The layout and presentation of cells is managed by the collection view and its corresponding layout object. To configure the content and appearance of your cell, you can set its contentConfiguration and backgroundConfiguration.

When to use a single data item in a uicollectionviewcell?

A single data item when that item is within the collection view’s visible bounds. You can use UICollectionViewCell as-is or subclass it to add additional properties and methods.

How do I register a cell in a collection view?

Instead, you register your specific cell subclass (or a nib file containing a configured instance of your class) using a cell registration. When you want a new instance of your cell class, call the dequeueConfiguredReusableCell (using:for:item:) method of the collection view object to retrieve one.

What are the background views of a cell?

In addition to the content view, the cell manages two background views that display the cell in its selected and unselected states. You typically don’t create instances of this class yourself.


2 Answers

You could implement -(void)prepareForReuse in your UICollectionViewCell subclass. and do your resetting there.

like image 177
Weston Avatar answered Oct 05 '22 05:10

Weston


You could try setting the URL for the cell to nil when the cell is finished displaying, it worked on my project.

-(void)collectionView:(UICollectionView *)cv didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{
    [(MyCollectionViewCell *)cell setUrlString:nil];
}

I hope this helps!

like image 25
architectpianist Avatar answered Oct 05 '22 05:10

architectpianist