Question

I am trying to use uiimage-from-animated-gif to load some GIFs into my UITableView Cells. But the problem is that everytime I try to load an image from my Cache, the cell halts a little before it scrolls.

This is the code I was using

postGif = (UIImageView *)[cell viewWithTag:104];

if ([[ImageCache sharedImageCache] DoesExist:post[@"gif"]] == true)
{
    image = [[ImageCache sharedImageCache] GetImage:post[@"gif"]];

    postGif.image = [UIImage animatedImageWithAnimatedGIFData:image];

}else
{
    dispatch_queue_t backgroundQueue = dispatch_queue_create("cacheImage", 0);

    dispatch_async(backgroundQueue, ^{

        NSData *imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:post[@"gif"]]];
        dispatch_async(dispatch_get_main_queue(), ^{

            // Add the image to the cache
            [[ImageCache sharedImageCache] AddImage:post[@"gif"] image:imageData];

            NSIndexPath* ind = [NSIndexPath indexPathForRow:0 inSection:indexPath.section];
            [self.feedTableView beginUpdates];
            [self.feedTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:ind] withRowAnimation:UITableViewRowAnimationNone];
            [self.feedTableView endUpdates];
        });
    });
}

postGif.layer.cornerRadius = 2.0;
postGif.layer.masksToBounds = YES;

[cell.contentView addSubview:postGif]; 

I tried background queue as well. but the Image load is really slow with it.

if ([[ImageCache sharedImageCache] DoesExist:post[@"gif"]] == true)
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
                                             (unsigned long)NULL), ^(void) {
        NSData *image = [[ImageCache sharedImageCache] GetImage:post[@"gif"]];

        postGif.image = [UIImage animatedImageWithAnimatedGIFData:image];
    });

}else
{
    dispatch_queue_t backgroundQueue = dispatch_queue_create("cacheImage", 0);

    dispatch_async(backgroundQueue, ^{

        NSData *imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:post[@"gif"]]];
        dispatch_async(dispatch_get_main_queue(), ^{

            // Add the image to the cache
            [[ImageCache sharedImageCache] AddImage:post[@"gif"] image:imageData];

            NSIndexPath* ind = [NSIndexPath indexPathForRow:0 inSection:indexPath.section];
            [self.feedTableView beginUpdates];
            [self.feedTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:ind] withRowAnimation:UITableViewRowAnimationNone];
            [self.feedTableView endUpdates];
        });
    });
}

I am not sure what am I doing wrong. maybe I am not grasping a concept.

Maycoff suggested that I should not modify properties of user interface objects (like a UIImageView) from a background queue and that I need to create the instance of UIImage on a background queue, can someone please explain it to me what is it that I am not grasping?

Thanks for your help in advance.

Was it helpful?

Solution

The problem in your earlier code was that you were creating the UIImage from the GIF data on the main queue. Since decoding a GIF (especially one with many frames) can take some time, you were blocking the main thread, which is why the table view stopped scrolling momentarily each time it needed to display another image.

The problem in your later code is that you are modifying the image property of a UIImageView on a background queue. You must only modify user interface objects on the main queue.

What you need to do is create the UIImage on a background queue, then dispatch back to the main queue to update the UIImageView's image property. Thus:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
                                         (unsigned long)NULL), ^(void) {
    NSData *data = [[ImageCache sharedImageCache] GetImage:post[@"gif"]];
    UIImage *image = [UIImage animatedImageWithAnimatedGIFData:data];
    dispatch_async(dispatch_get_main_queue(), ^{
        postGif.image = image;
    }
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top