Search code examples
iosobjective-cios7uicollectionviewuicollectionviewcell

UICollectionView images loading issue


UICollectionView is used to display images. It works fine.

Issue is when I scroll UICollectionView, some of the cells which were visible are now non-visible and when I scroll back so that they are visible again, I see that they are not properly displayed.

So what happens is that imageA is at index 0 and imageB is at index 1. Now after scrolling and coming back original scroll position when those cells are loaded again, their position is either switched or both the cell have same images.

Initially :

enter image description here

After reloading cells :

enter image description here

Code :

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

    DLog(@"url at index %d : %@", indexPath.row, ((MyObject *)[self.list.array objectAtIndex:indexPath.row]).imageUrl);

    MyObject *object = (MyObject *)[self.list.array objectAtIndex:indexPath.row];

    // Get image in separate thread
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // Get image to display
        UIImage * tempImage = object.image;

        if (tempImage)
        {
            // Run code to set image to UIImageView in main thread only.
            dispatch_async(dispatch_get_main_queue(), ^{

                cell.imageView.image = tempImage;
            });
        }
        else
        {
            // Download failed.
            DLog(@"Downloaded image is nil.");
        }
    });

    return cell;
}

I log the value of image url and it is logging correct value.


Solution

  • I also used that trick, but the threads and the indexes between threads make a mess so I searched and I found a great library on GitHub.

    You just need to #import <SDWebImage/UIImageView+WebCache.h> to your project, and you can define also the placeholder when image is being downloaded with just this code:

    -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
        MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MyCell"
                                                                 forIndexPath:indexPath];
    
        DLog(@"url at index %d : %@", indexPath.row, ((MyObject *)[self.list.array objectAtIndex:indexPath.row]).imageUrl);
    
        MyObject *object = (MyObject *)[self.list.array objectAtIndex:indexPath.row];
    
        [cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
                       placeholderImage:[UIImage imageNamed:@"placeholder.png"]];
    
        return cell;
    }
    

    It also cache downloaded images and gives you great performance.

    Hope it will help you!