我們知道Gif是由一陣陣畫面組成的,而且每一幀畫面播放的時常可能會不相等,觀察上面兩個例子,發現他們都沒有對Gif中每一幀的顯示時常做處理,這樣的結果就是整個Gif中每一幀畫面都是以固定的速度向前播放,很顯然這并不總會符合需求。
		 
		  于是自己寫一個解析Gif的工具類,解決每一幀畫面并遵循每一幀所對應的顯示時間進行播放。
		 
		  程序的思路如下:
		 
		  1、首先使用ImageIO庫中的CGImageSource家在Gif文件。
		 
		  2、通過CGImageSource獲取到Gif文件中的總的幀數,以及每一幀的顯示時間。
		 
		  3、通過CAKeyframeAnimation來完成Gif動畫的播放。
		 
		  下面直接上我寫的解析和播放Gif的工具類的代碼:
		 
			//
			//  SvGifView.h
			//  SvGifSample
			//
			//  Created by maple on 3/28/13.
			//  Copyright (c) 2013 smileEvday. All rights reserved.
			//
			
			#import <UIKit/UIKit.h>
@interface SvGifView : UIView
			
			/*
			 * @brief desingated initializer
			 */
			- (id)initWithCenter:(CGPoint)center fileURL:(NSURL*)fileURL;
			/*
			 * @brief start Gif Animation
			 */
			- (void)startGif;
			/*
			 * @brief stop Gif Animation
			 */
			- (void)stopGif;
			/*
			 * @brief get frames image(CGImageRef) in Gif
			 */
			+ (NSArray*)framesInGif:(NSURL*)fileURL;
			
			@end
			
			//
			//  SvGifView.m
			//  SvGifSample
			//
			//  Created by maple on 3/28/13.
			//  Copyright (c) 2013 smileEvday. All rights reserved.
			//
			#import "SvGifView.h"
			#import <ImageIO/ImageIO.h>
			#import <QuartzCore/CoreAnimation.h>
			/*
			 * @brief resolving gif information
			 */
			void getFrameInfo(CFURLRef url, NSMutableArray *frames, NSMutableArray *delayTimes, CGFloat *totalTime,CGFloat *gifWidth, CGFloat *gifHeight)
			{
			    CGImageSourceRef gifSource = CGImageSourceCreateWithURL(url, NULL);
			    
			    // get frame count
			    size_t frameCount = CGImageSourceGetCount(gifSource);
			    for (size_t i = 0; i < frameCount; ++i) {
			        // get each frame
			        CGImageRef frame = CGImageSourceCreateImageAtIndex(gifSource, i, NULL);
			        [frames addObject:(id)frame];
			        CGImageRelease(frame);
			        
			        // get gif info with each frame
			        NSDictionary *dict = (NSDictionary*)CGImageSourceCopyPropertiesAtIndex(gifSource, i, NULL);
			        NSLog(@"kCGImagePropertyGIFDictionary %@", [dict valueForKey:(NSString*)kCGImagePropertyGIFDictionary]);
			        
			        // get gif size
			        if (gifWidth != NULL && gifHeight != NULL) {
			            *gifWidth = [[dict valueForKey:(NSString*)kCGImagePropertyPixelWidth] floatValue];
			            *gifHeight = [[dict valueForKey:(NSString*)kCGImagePropertyPixelHeight] floatValue];
			        }
			        
			        // kCGImagePropertyGIFDictionary中kCGImagePropertyGIFDelayTime,kCGImagePropertyGIFUnclampedDelayTime值是一樣的
			        NSDictionary *gifDict = [dict valueForKey:(NSString*)kCGImagePropertyGIFDictionary];
			        [delayTimes addObject:[gifDict valueForKey:(NSString*)kCGImagePropertyGIFDelayTime]];
			        
			        if (totalTime) {
			            *totalTime = *totalTime + [[gifDict valueForKey:(NSString*)kCGImagePropertyGIFDelayTime] floatValue];
			        }
			    }
			}
			@interface SvGifView() {
			    NSMutableArray *_frames;
			    NSMutableArray *_frameDelayTimes;
			    
			    CGFloat _totalTime;         // seconds
			    CGFloat _width;
			    CGFloat _height;
			}
@end
@implementation SvGifView
			
			- (id)initWithCenter:(CGPoint)center fileURL:(NSURL*)fileURL;
			{
			    self = [super initWithFrame:CGRectZero];
			    if (self) {
			        
			        _frames = [[NSMutableArray alloc] init];
			        _frameDelayTimes = [[NSMutableArray alloc] init];
			        
			        _width = 0;
			        _height = 0;
			        
			        if (fileURL) {
			            getFrameInfo((CFURLRef)fileURL, _frames, _frameDelayTimes, &_totalTime, &_width, &_height);
			        }
			        
			        self.frame = CGRectMake(0, 0, _width, _height);
			        self.center = center;
			    }
			    
			    return self;
			}
			+ (NSArray*)framesInGif:(NSURL *)fileURL
			{
			    NSMutableArray *frames = [NSMutableArray arrayWithCapacity:3];
			    NSMutableArray *delays = [NSMutableArray arrayWithCapacity:3];
			    
			    getFrameInfo((CFURLRef)fileURL, frames, delays, NULL, NULL, NULL);
			    
			    return frames;
			}
			- (void)startGif
			{
			    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
			    
			    NSMutableArray *times = [NSMutableArray arrayWithCapacity:3];
			    CGFloat currentTime = 0;
			    int count = _frameDelayTimes.count;
			    for (int i = 0; i < count; ++i) {
			        [times addObject:[NSNumber numberWithFloat:(currentTime / _totalTime)]];
			        currentTime += [[_frameDelayTimes objectAtIndex:i] floatValue];
			    }
			    [animation setKeyTimes:times];
			    
			    NSMutableArray *images = [NSMutableArray arrayWithCapacity:3];
			    for (int i = 0; i < count; ++i) {
			        [images addObject:[_frames objectAtIndex:i]];
			    }
			    
			    [animation setValues:images];
			    [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
			    animation.duration = _totalTime;
			    animation.delegate = self;
			    animation.repeatCount = 5;
			    
			    [self.layer addAnimation:animation forKey:@"gifAnimation"];
			}
			- (void)stopGif
			{
			    [self.layer removeAllAnimations];
			}
			// remove contents when animation end
			- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
			{
			    self.layer.contents = nil;
			}
			// Only override drawRect: if you perform custom drawing.
			// An empty implementation adversely affects performance during animation.
			- (void)drawRect:(CGRect)rect
			{
			    // Drawing code
			}
			
			@end
		
		  代碼很短也比較容易,就不一一解釋了。最開始的那個C函數主要就是用來解析Gif的,之所以用C函數是因為我要返回多個信息,而Objective-c只能返回一個參數,而且Objective-c和C語言可以很方便的混合編程。
另外再介紹兩種使用UIImageView的方法:
1. 使用UIWebView播放
// 設定位置和大小
CGRect frame = CGRectMake(50,50,0,0);
frame.size = [UIImage imageNamed:@"guzhang.gif"].size;
// 讀取gif圖片數據
NSData *gif = [NSData dataWithContentsOfFile: [[NSBundle mainBundle] pathForResource:@"guzhang" ofType:@"gif"]];
// view生成
UIWebView *webView = [[UIWebView alloc] initWithFrame:frame];
webView.userInteractionEnabled = NO;//用戶不可交互
[webView loadData:gif MIMEType:@"image/gif" textEncodingName:nil baseURL:nil];
[self.view addSubview:webView];
[webView release];
		2.將gif圖片分解成多張png圖片,使用UIImageView播放。
		代碼如下:
UIImageView *gifImageView = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
NSArray *gifArray = [NSArray arrayWithObjects:[UIImage imageNamed:@"1"],
[UIImage imageNamed:@"2"],
[UIImage imageNamed:@"3"],
[UIImage imageNamed:@"4"],
[UIImage imageNamed:@"5"],
[UIImage imageNamed:@"6"],
[UIImage imageNamed:@"7"],
[UIImage imageNamed:@"8"],
[UIImage imageNamed:@"9"],
[UIImage imageNamed:@"10"],
[UIImage imageNamed:@"11"],
[UIImage imageNamed:@"12"],
[UIImage imageNamed:@"13"],
[UIImage imageNamed:@"14"],
[UIImage imageNamed:@"15"],
[UIImage imageNamed:@"16"],
[UIImage imageNamed:@"17"],
[UIImage imageNamed:@"18"],
[UIImage imageNamed:@"19"],
[UIImage imageNamed:@"20"],
[UIImage imageNamed:@"21"],
[UIImage imageNamed:@"22"],nil];
gifImageView.animationImages = gifArray; //動畫圖片數組
gifImageView.animationDuration = 5; //執行一次完整動畫所需的時長
gifImageView.animationRepeatCount = 1; //動畫重復次數
[gifImageView startAnimating];
[self.view addSubview:gifImageView];
[gifImageView release];
注意:這個方法,如果gif動畫每楨間的時間間隔不同,不能達到此效果。




















