Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9015043
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 16, 20262026-06-16T03:39:13+00:00 2026-06-16T03:39:13+00:00

I have a UICollectionView , but the same methods should apply to UITableViews .

  • 0

I have a UICollectionView, but the same methods should apply to UITableViews. Each of my cells contains an image I load from disk, which is a slow operation. To mitigate this, I use an async dispatch queue. This works fine, but quickly scrolling results in these operations stacking up, such that the cell will change its image from one to another in sequence, until finally stopping at the last call.

In the past, I’ve done a check to see if the cell was still visible, and if not I don’t continue. However, this is not working with UICollectionView, and anyway it is not efficient. I am considering migrating to use NSOperations, which can be cancelled, so that only the last call to modify the cell will go through. I could possibly do this by checking if the operation had finished in the prepareForReuse method, and cancelling it if not. I’m hoping someone has dealt with this issue in the past and can provide some tips or a solution.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-16T03:39:14+00:00Added an answer on June 16, 2026 at 3:39 am

    Session 211 – Building Concurrent User Interfaces on iOS, from WWDC 2012, discusses the problem of the cell’s image changing as the background tasks catch up (starting at 38m15s).

    Here’s how you solve that problem. After you’ve loaded the image on the background queue, use the index path to find the current cell, if any, that’s displaying the item containing that image. If you get a cell, set the cell’s image. If you get nil, there’s no cell currently displaying that item so just discard the image.

    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
        MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
        cell.imageView.image = nil;
        dispatch_async(myQueue, ^{
            [self bg_loadImageForRowAtIndexPath:indexPath];
        });
        return cell;
    }
    
    - (void)bg_loadImageForRowAtIndexPath:(NSIndexPath *)indexPath {
        // I assume you have a method that returns the path of the image file.  That
        // method must be safe to run on the background queue.
        NSString *path = [self bg_pathOfImageForItemAtIndexPath:indexPath];
        UIImage *image = [UIImage imageWithContentsOfFile:path];
        // Make sure the image actually loads its data now.
        [image CGImage];
    
        dispatch_async(dispatch_get_main_queue(), ^{
            [self setImage:image forItemAtIndexPath:indexPath];
        });
    }
    
    - (void)setImage:(UIImage *)image forItemAtIndexPath:(NSIndexPath *)indexPath {
        MyCell *cell = (MyCell *)[collectionView cellForItemAtIndexPath:indexPath];
        // If cell is nil, the following line has no effect.
        cell.imageView.image = image;
    }
    

    Here’s an easy way to reduce the “stacking up” of background tasks loading images that the view no longer needs. Give yourself an NSMutableSet instance variable:

    @implementation MyViewController {
        dispatch_queue_t myQueue;
        NSMutableSet *indexPathsNeedingImages;
    }
    

    When you need to load an image, put the index path of the cell in the set and dispatch a task that takes one index path out of the set and loads its image:

    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
        MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
        cell.imageView.image  = nil;
        [self addIndexPathToImageLoadingQueue:indexPath];
        return cell;
    }
    
    - (void)addIndexPathToImageLoadingQueue:(NSIndexPath *)indexPath {
        if (!indexPathsNeedingImages) {
            indexPathsNeedingImages = [NSMutableSet set];
        }
        [indexPathsNeedingImages addObject:indexPath];
        dispatch_async(myQueue, ^{ [self bg_loadOneImage]; });
    }
    

    If a cell stops being displayed, remove the cell’s index path from the set:

    - (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
        [indexPathsNeedingImages removeObject:indexPath];
    }
    

    To load an image, get an index path from the set. We have to dispatch back to the main queue for this, to avoid a race condition on the set:

    - (void)bg_loadOneImage {
        __block NSIndexPath *indexPath;
        dispatch_sync(dispatch_get_main_queue(), ^{
            indexPath = [indexPathsNeedingImages anyObject];
            if (indexPath) {
                [indexPathsNeedingImages removeObject:indexPath];
            }
        }
    
        if (indexPath) {
            [self bg_loadImageForRowAtIndexPath:indexPath];
        }
    }
    

    The bg_loadImageForRowAtIndexPath: method is the same as above. But when we actually set the image in the cell, we also want to remove the cell’s index path from the set:

    - (void)setImage:(UIImage *)image forItemAtIndexPath:(NSIndexPath *)indexPath {
        MyCell *cell = (MyCell *)[collectionView cellForItemAtIndexPath:indexPath];
        // If cell is nil, the following line has no effect.
        cell.imageView.image = image;
    
        [indexPathsNeedingImages removeObject:indexPath];
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a UICollectionView displaying image thumbnails. Each Image View in the grid has
I have a UICollectionView , and it works great, but I have a doubt.
I recently started playing with the awesome UICollectionView API, making reasonable progress, but have
I have a collection view that contains different custom cells. These cells contain different
So my rootViewController contains a UICollectionView with a Custom UICollectionViewCell. I have a label
Have deployed numerous report parts which reference the same view however one of them
have a problem. At first look at this HTML <div id=map style=background-image: url(map.png); width:
I have a UICollectionViewController that I load when a user turns their iPad so
I have a UICollectionView which uses UICollectionViewDelegateFlowLayout . I've added a method which changes
I have a UICollectionView showing several items. I also have an edit button in

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.