一·实现的各种方式
1.将GIF图片分解成多张PNG图片,使用UIImageView播放(内存消耗过大)
2.使用YYImage中的YYAnimatedImageView播放,推荐,内存优化的挺好,是个高性能的框架。
这里就不详细说明YYAnimatedImageView的实现方式了。其核心思想就是 解压gif成图片数组,利用CADisplaylink进行按帧动画显示
二·自己实现播放gif,学习内部细节
1.属性
/// 用于展示帧动画
@property (nonatomic, strong) CADisplayLink *displayLink;
/// 图片数组
@property (nonatomic, strong) NSArray *imageArray;
/// 当前帧
@property (nonatomic, assign) NSInteger currentIndex;
/// 是否正在显示
@property (nonatomic, assign, getter=isAnimation) BOOL animation;
/// 总的时间
@property (nonatomic, assign) NSTimeInterval timeDuration;
/// 是否重复
@property (nonatomic, assign, getter=isRepeat) BOOL repeat;
2.解压gif
/// 获取资源
- (void)loadGif:(NSString *)gif isRepeat:(BOOL)repeat {
self.repeat = repeat;
//1.加载Gif图片,转换成Data类型
NSString *path = [NSBundle.mainBundle pathForResource:gif ofType:@"gif"];
NSData *data = [NSData dataWithContentsOfFile:path];
//2.将data数据转换成CGImageSource对象
CGImageSourceRef imageSource = CGImageSourceCreateWithData(CFBridgingRetain(data), nil);
size_t imageCount = CGImageSourceGetCount(imageSource);
//3.遍历所有图片
NSMutableArray *images = [NSMutableArray array];
NSTimeInterval totalDuration = 0;
for (int i = 0; i<imageCount; i++) {
//取出每一张图片
CGImageRef cgImage = CGImageSourceCreateImageAtIndex(imageSource, i, nil);
UIImage *image = [UIImage imageWithCGImage:cgImage];
[images addObject:image];
//持续时间
NSDictionary *properties = (__bridge_transfer NSDictionary*)CGImageSourceCopyPropertiesAtIndex(imageSource, i, nil);
NSDictionary *gifDict = [properties objectForKey:(__bridge NSString *)kCGImagePropertyGIFDictionary];
NSNumber *frameDuration =
[gifDict objectForKey:(__bridge NSString *)kCGImagePropertyGIFDelayTime];
totalDuration += frameDuration.doubleValue;
}
self.imageArray = [images copy];
self.timeDuration = totalDuration;
self.currentIndex = 0;
}
3.利用CADisplaylink实现播放
- (void)display {
if ([self.imageArray isEqual:nil] || self.imageArray.count == 0) {
[self stopAnimating];
return;
}
if (self.currentIndex > self.imageArray.count) {
if (self.repeat) {
self.currentIndex = 0;
[self startAnimating];
return;
} else {
[self stopAnimating];
return;
}
}
}
- (CADisplayLink *)displayLink {
if (!_displayLink) {
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(display)];
// 当把 CADisplayLink 对象添加到 Runloop 中后,selector就能被周期性调用
[self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}
return _displayLink;
}