UIImageView 播放 GIF

这篇博客探讨了在iOS中播放GIF的三种方式:UIWebView、UIImageView自带动画和CADisplayLink。作者指出UIWebView无法控制动画,UIImageView可能导致内存暴涨,而CADisplayLink提供了更好的内存管理和动画控制。文章提供了详细的实现源码,特别是如何保持GIF每一帧的原始间隔时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<span style="font-family: Arial, Helvetica, sans-serif;">	</span><span style="font-family: Arial, Helvetica, sans-serif; "><strong><span style="font-size:18px;">本文主要解析GIF图片的每一帧,然后用定时器循环播放实现GIF动画。</span></strong></span>

源于这篇GIF动画的深思,还是一些需求产生的:如,我只想看GIF动画播放一次(2,3,4...),然后做其他事;或者动画每帧间隔太慢了,想调整怎么办?等等。。。,作为程序员,大家想要的感觉就是,一切尽在我的掌控之中,我想要停就马上停止,想要动就立刻动起来。不好的情况是,我没法控制它,我想要干另外一件事了,它还不能停止。


在iOS平台,大家所熟知的有三种播放方式:

1、用UIWebView 实现:也是比较简单的方式,这种方式主要就是把GIF图片构造入一个html中,然后让UIWebView去解析这个html,然后播放动画。

这种方式的缺点:使用者无法知道这个动画循环一次完成,反正是uiwebview解析,我只看到动画,其他的无法控制。

2、UIImageView自身支持的动画:简单的把GIF每一帧图片解析出来,然后生成UIImage数组,

self.imageView.animationImages = imagesArray;

 self.imageView.animationDuration = imageDuration;

   [self.imageView startAnimating];

然后就可以动画就开始了,或者使用CAKeyframeAnimation 也可以。这几个都一样的是我们都要解析GIF内的每一帧图片,然后组成一个图片数组来播放动画。

缺点:GIF由很多帧图片组成,然后播放时有个播放帧时间间隔,每一帧的间隔是不一样的。若是上面这种方式的动画播放,它就会设置一个平均每帧时间,这样播放出来的动画也许就不是原来的效果了。

更严重的是GIF图片稍大一点内存就暴涨,一个600KB的GIF解析出来后由50张UIImage,这时候内存会涨到70MB,及时这个应用什么也不干;刚开始我发现好像也能接受,但我们有一个5MB的GIF,解析后有200多张UIImage,这时候内存一下涨到200MB,马上应用就crash了。

 

 3、利用CADisplayLink或NSTimer循环播放:也就是我更推荐的一种

存储图片信息采用 CGImageSourceRef:

<span style="font-size:18px;">   <span style="white-space:pre">	</span>_gifSourceRef = CGImageSourceCreateWithURL((__bridge CFURLRef)[NSURL fileURLWithPath:gifPath], NULL);
   <span style="white-space:pre">	</span> self.frameCount = CGImageSourceGetCount(_gifSourceRef);</span>
</pre><pre name="code" class="objc">
然后在定时器中不断更新图片,根据每一帧的间隔来更换,就可以达到效果:

<span style="font-size:18px;"> <span style="white-space:pre">	</span>CGImageRef ref = CGImageSourceCreateImageAtIndex(_gifSourceRef, self.currentFrameIndex, NULL);
        self.layer.contents = (__bridge id)(ref);
        CGImageRelease(ref);</span>

解析每一帧的时间可以用下面的方法:

<span style="font-size:18px;">- (float)frameDurationAtIndex:(size_t)index
{
    CFDictionaryRef dictRef = CGImageSourceCopyPropertiesAtIndex(_gifSourceRef, index, NULL);
    NSDictionary *dict = (__bridge NSDictionary *)dictRef;
    NSDictionary *gifDict = (dict[(NSString *)kCGImagePropertyGIFDictionary]);
    NSNumber *unclampedDelayTime = gifDict[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
    NSNumber *delayTime = gifDict[(NSString *)kCGImagePropertyGIFDelayTime];
    CFRelease(dictRef);
    
    if (unclampedDelayTime.floatValue) {
        return unclampedDelayTime.floatValue;
    }else if (delayTime.floatValue) {
        return delayTime.floatValue;
    }else{
        return 1/30.f;
    }
}</span>

这样我们就可以在定时器响应函数里做处理来更换图片,实现动画。


若想看详细实现源码,请看GitHubDemo,主要实现第三种播放方式,因为在内存方面,保持原动画效果更好的方式(每一帧的间隔)。












   







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值