Clinton Jooooones
Clinton Jooooones

Reputation: 1037

Why does loading images asynchronously take forever?

I have a UICollectionView displaying a bunch of images. If I don't load the images asynchronously the scrolling is very choppy and provides a poor user experience. When I load the images asynchronously the scrolling is smooth but it takes a good 5 to 10 seconds to load each image.

Why does it take so long for images to appear when loaded in the background? Here is my code for the background thread which is inside of the cellForItemAtIndexPath delegate:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    UIImageView *bg = (id)self.backgroundView;
    UIImageView *selbg = (id)self.selectedBackgroundView;

    if (![bg isKindOfClass:[UIImageView class]])
        bg = [[UIImageView alloc] initWithImage:thumb];
    else
        [bg setImage:thumb];

    if (![selbg isKindOfClass:[UIImageView class]]){
        selbg = [[UIImageView alloc] initWithImage:thumb];
        coloroverlay = [[UIView alloc] initWithFrame:selbg.bounds];
        [coloroverlay setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
        [selbg addSubview:coloroverlay];
    } else
        [selbg setImage:thumb];

    [bg setContentMode:UIViewContentModeScaleAspectFill];
    [bg setTag: 1];
    [coloroverlay setBackgroundColor:[col colorWithAlphaComponent:0.33f]];
    [selbg setContentMode:UIViewContentModeScaleAspectFill];

    dispatch_sync(dispatch_get_main_queue(), ^{
        [self setBackgroundView:bg];
        [self setSelectedBackgroundView:selbg];
    });
});

EDIT: As @geraldWilliam pointed out, I shouldn't be accessing views from the secondary thread. Here is what I have updated my code to and fixed the issue of images getting set to the wrong cell:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    UIImageView *bg = (id)self.backgroundView;
    UIImageView *selbg = (id)self.selectedBackgroundView;

    if (![bg isKindOfClass:[UIImageView class]]) bg = [[UIImageView alloc] initWithImage:thumb];

    if (![selbg isKindOfClass:[UIImageView class]]){
        selbg = [[UIImageView alloc] initWithImage:thumb];
        coloroverlay = [[UIView alloc] initWithFrame:selbg.bounds];
        [coloroverlay setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
        [selbg addSubview:coloroverlay];
    }


    dispatch_sync(dispatch_get_main_queue(), ^{
        [bg setImage:thumb];
        [selbg setImage:thumb];

        [bg setContentMode:UIViewContentModeScaleAspectFill];
        [bg setTag: 1];
        [coloroverlay setBackgroundColor:[col colorWithAlphaComponent:0.33f]];
        [selbg setContentMode:UIViewContentModeScaleAspectFill];

        [self setBackgroundView:bg];
        [self setSelectedBackgroundView:selbg];
    });
});

Upvotes: 0

Views: 109

Answers (2)

Douglas Hill
Douglas Hill

Reputation: 1547

I strongly recommend watching WWDC 2012 Session 211: Building Concurrent User Interfaces on iOS, which is the best WWDC session ever. It’s full of clearly presented, practical advice.

Doing stuff with UIImageView off the main queue is worrying and should be fixed, but is probably not the cause of slowness. You haven’t showed us where thumb comes from, which is likely the slow bit.

Upvotes: 0

user1078170
user1078170

Reputation:

Most of the code you have here is fine for the main queue. The loading of the image should be on a global queue, but the rest, especially setting the image view's image, should be on the main queue. What's going on in your code is that you're dispatching back to the main queue to set the background view but leaving the assignment of the image property in the background. So, try something like:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:myImageURL]];
  dispatch_sync(dispatch_get_main_queue(), ^{
    imageView.image = image;
    [self setBackgroundView:imageView];
  });
});

Upvotes: 3

Related Questions