Load many gif to UICollectionView

I am facing problem when I download gif images and add in to collection view. gif images are download well, but when i try to scroll very very quickly it's crash

Please help. I have two solutions

    /*
    cellForGif.layer.borderColor = [[UIColor colorWithRed:54.0/255.f green:56.0/255.f blue:67.0/255.f alpha:1.0]CGColor];
    cellForGif.layer.borderWidth = 0.7;
    FLAnimatedImage __block *gifImage = nil;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        gifImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%li", (long)indexPath.row] ofType:@"gif"]]];

        dispatch_async(dispatch_get_main_queue(), ^{

            cellForGif.gifImage.animatedImage = gifImage;
            cellForGif.linkOnGif = [self.linksArrayOnGifs objectAtIndex:indexPath.row];
           //gifImage = nil;
        });
    });
    return cellForGif;
     */
    cellForGif.layer.borderColor = [[UIColor colorWithRed:54.0/255.f green:56.0/255.f blue:67.0/255.f alpha:1.0]CGColor];
    cellForGif.layer.borderWidth = 0.7;
    FLAnimatedImage *gifImage = nil;
        gifImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%li", (long)indexPath.row] ofType:@"gif"]]];
            cellForGif.gifImage.animatedImage = gifImage;
            cellForGif.linkOnGif = [self.linksArrayOnGifs objectAtIndex:indexPath.row];
            //gifImage = nil;

    return cellForGif; 

Upvotes: 8

Views: 2811

Answers (2)

Deep Gandhi
Deep Gandhi

Reputation: 395

swift extension based on Kampai's answer:

extension UIImageView {
    func setGif(_ url: String) {
        DispatchQueue.global(qos: .default).async {
             do {
                let gifData = try Data(contentsOf: URL(string: url) ?? URL(fileURLWithPath: ""))
                DispatchQueue.main.async {
                    self.image = UIImage.sd_image(withGIFData: gifData)
                }
            } catch let error {
                DispatchQueue.main.async {
                    self.image = UIImage(named: "defaultImg")// set default image here
                }
                print(error)
            }
        }
    }
}

use it as:

cell.imageGif.setGif("image url")

Upvotes: 0

Mehul Patel
Mehul Patel

Reputation: 23053

You need to change your approach.

You have to load all images before going to set them in UICollectionViewCell.

Let's say create an NSArray contains all gif images. After images are loaded successfully then set them to the cell.

By observing straight from your code, I see that you load an image from the main bundle in cellForItemAtIndexPath method. So it is obvious that it will take some time very little (nano sec). But that is also considered large when there are a large amount of data in a cell.

And it is possible that line

[NSData dataWithContentsOfFile:[[NSBundle mainBundle]

will return nil when you scroll very very quickly.

Add a comment if it is still not clear.

EDIT:

Loading images in the background will not affect UI and scrolling will be smoother.

Also, put try-catch block in that method to check what you have missed.

    cellForGif.layer.borderColor = [[UIColor colorWithRed:54.0/255.f green:56.0/255.f blue:67.0/255.f alpha:1.0]CGColor];
    cellForGif.layer.borderWidth = 0.7;

    @try {
        FLAnimatedImage __block *gifImage = nil;        
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            gifImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%li", (long)indexPath.row] ofType:@"gif"]]];

            dispatch_async(dispatch_get_main_queue(), ^{

                cellForGif.gifImage.animatedImage = gifImage;
                cellForGif.linkOnGif = [self.linksArrayOnGifs objectAtIndex:indexPath.row];
                //gifImage = nil;
            });
        });
    }
    @catch (NSException *exception) {
        NSLog(@"Exception :%@",exception.debugDescription);
    }

Upvotes: 4

Related Questions