TienLe
TienLe

Reputation: 623

Asynchronously load images from document directory into UICollectionView

I am trying to load images from document directory into UICollectionView. It works: smooth, fast....(lol). But I get one issue: when I call [collectionView reloadData], images flicker(once time). Here is my code:

- (UICollectionViewCell*)collectionView:(UICollectionView *)collectionView_ cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    NSString *cellIdentifier = NSStringFromClass([AFMyRecentCollectionViewCell class]);
    AFMyRecentCollectionViewCell *cell = (AFMyRecentCollectionViewCell*)[collectionView_ dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
    AFMyRecentObject *recent = [[AFRecentManager sharedInstance].arrayRecent objectAtIndex:indexPath.row];

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
    dispatch_async(queue, ^{
        UIImage *image;
        NSFileManager *fileManager = [NSFileManager defaultManager];
        NSString *filePath = [self databasePathWithPathComponent:[NSString stringWithFormat:@"%@.jpg", recent.id_film]];
        if ([fileManager fileExistsAtPath:filePath] == YES) {
            image = [UIImage imageWithContentsOfFile:filePath];
        }

        dispatch_async(dispatch_get_main_queue(), ^{
            if (image) {
                cell.imageView.image = image;
            } else {
                cell.imageView.image = [UIImage imageNamed:@"loadding.png"];
            }
        });
    });

    cell.layer.shouldRasterize = YES;
    cell.layer.rasterizationScale = [UIScreen mainScreen].scale;

    return cell;
}

- (NSString *)databasePathWithPathComponent:(NSString*)pathComponent {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex: 0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:pathComponent];
    return path;
}

Upvotes: 3

Views: 1390

Answers (3)

0yeoj
0yeoj

Reputation: 4550

You have to place and default/placeholder image to prevent that..

    // this prevents the flicker/blinks
    cell.imageView.image = nil; // if you dont have any image as placeholder

    //since you have 
    cell.imageView.image = [UIImage imageNamed:@"loadding.png"]; // this i assume your placeholder image?

    dispatch_async(queue, ^{
        //your codes..
        dispatch_async(dispatch_get_main_queue(), ^{
            // your codes..
        });
    });

Upvotes: 3

Rob
Rob

Reputation: 437872

The problem is that you're initiating the asynchronous update of the image view, but if the cell is reused, you're going to see the old image there. So, before you dispatch_async the process to retrieve the image, make sure you set cell.imageView.image to nil first. So make sure you never see the prior image in the cell before initiating the asynchronous retrieval of the correct image.

Upvotes: 1

Nilesh Patel
Nilesh Patel

Reputation: 6394

I have faced same issue of flickring the images & solved it using below approach.

Apply same lazy loading concept. Like create one dictionary object to store all images before displaying, Before getting the image from the document directory check wether that images is there in the dictionary if it's there then then user that image to display it.

If image is not there in the dictionary then do database operation.

Hope this will resolve your issue.

Upvotes: 1

Related Questions