One, the introduction

In iOS development, UIImageView is responsible for rendering image data, and UIImageView also has a frame animation method to play a set of images, but for GIF data, UIImageView does not have a ready interface for developers to use. In iOS, there are generally two ways to play GIF dynamic images. One way is to parse the data in THE GIF file through the method of ImageIO framework, and then use coreAnimation to play GIF animations. The other way is simple, and can directly render GIF images through webView.

Add a category to the native UIImageView to support GIF playback

GIF dynamic image file contains a group of pictures and their information, the information mainly records the playback time of each frame of picture, if we get all the pictures in the GIF file and get the playback time of each frame of picture, we can add core animation method for UIImageView to let it play the GIF content.

First parse the data in the GIF file as follows:

#import <ImageIO/ imageio.h >// the method used to parse GIF file data will be passed in the block -(void)getGifImageWithUrk:(NSURL) *)urlreturnData:(void(^)(NSArray<UIImage *> * imageArray,NSArray<NSNumber *>*timeArray,CGFloat TotalTime,NSArray<NSNumber *>* widths,NSArray<NSNumber *>* heights))dataBlock{// Read GIF files as image data by the file url reference CGImageSourceRef  source = CGImageSourceCreateWithURL((CFURLRef)url, NULL); Size_t count = CGImageSourceGetCount(source); // Define a variable to record the GIF playback round time float allTime=0; NSMutableArray * imageArray = [[NSMutableArray alloc]init]; NSMutableArray * timeArray = [[NSMutableArray alloc]init]; NSMutableArray * widthArray = [[NSMutableArray alloc]init]; // The height of each image NSMutableArray * heightArray = [[NSMutableArray alloc]init]; For (size_t I =0; i<count; i++) {CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL); [imageArray addObject:(__bridge UIImage *)(image)]; CGImageRelease(image); / / get image information NSDictionary * info = (__bridge NSDictionary *) CGImageSourceCopyPropertiesAtIndex (source, I, NULL); CGFloat width = [[info objectForKey:(__bridge NSString *)kCGImagePropertyPixelWidth] floatValue]; CGFloat height = [[info objectForKey:(__bridge NSString *)kCGImagePropertyPixelHeight] floatValue]; [widthArray addObject:[NSNumber numberWithFloat:width]]; [heightArray addObject:[NSNumber numberWithFloat:height]]; NSDictionary * timeDic = [info objectForKey:(__bridge NSString *)kCGImagePropertyGIFDictionary]; CGFloat time = [[timeDic objectForKey:(__bridge NSString *)kCGImagePropertyGIFDelayTime]floatValue]; allTime+=time; [timeArray addObject:[NSNumber numberWithFloat:time]]; }dataBlock(imageArray,timeArray,allTime,widthArray,heightArray); }Copy the code

Add a method to UIImageView to set the GIF content:

-(void)yh_setImage:(NSURL *)imageUrl{__weak id __self = self; [self getGifImageWithUrk:imageUrl returnData:^(NSArray<UIImage *> *imageArray, NSArray<NSNumber *> *timeArray, CGFloat totalTime, NSArray<NSNumber *> *widths, NSArray<NSNumber *> *heights) {CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];NSMutableArray * times = [[NSMutableArray alloc]init];float currentTime = For (int I =0; I < imagearray.count; I ++) {[times addObject:[NSNumber numberWithFloat:currentTime/totalTime]];currentTime+=[timeArray[i] floatValue];}[animation setKeyTimes:times];[animation  setValues:imageArray];[animation setTimingFunction:[CAMediaTimingFunction FunctionWithName: kCAMediaTimingFunctionLinear]]; / / set cycle animation. RepeatCount = MAXFLOAT; / / set the total duration animation broadcast. Duration = //Layer add [[(UIImageView *)__self Layer]addAnimation: Animation forKey:@"gifAnimation"];}]; }Copy the code

The following is an example of the code used:

UIImageView * imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0,0, 320, 200)]; NSURL * url = [[NSURL alloc]initFileURLWithPath:[[NSBundle mainBundle] pathForResource:imageName ofType:nil]]; [imageView yh_setImage:url]; [self.view addSubview:imageView];Copy the code

Use UIWebView to load GIF data

UIWebView in iOS is very powerful. You can use UIWebView as the carrier to display GIF images. And this method is very simple, the code is as follows:

/ / read the GIF data NSData * gifData = [NSData dataWithContentsOfURL: imageUrl]; UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)]; / / cancel the rebound effect webView. ScrollView. Bounces = NO; webView.backgroundColor = [UIColor clearColor]; // Set the zoom mode webView.scalesPageToFit = YES; // loadData with webView [webView loadData:gifData MIMEType:@"image/ GIF "textEncodingName:nil baseURL:nil];Copy the code

Four, the pros and cons of two ways to load GIF dynamic graph

After testing, in terms of loading speed, UIImageView loading method is faster, UIWebView loading method is a little longer, but in terms of performance, WebView performance is better, GIF dynamic image playback is more smooth. For example, although the WebView loading method is better, in many cases, the native UIImageView gives developers more freedom to extend.

Look at the original

Recommend a 👇 :

If you want to advance together, add the exchange group 642363427