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
An object that manages an ordered collection of data items and presents them using customizable layouts.
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.
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.
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.
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.
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.
You could implement -(void)prepareForReuse
in your UICollectionViewCell subclass. and do your resetting there.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With