iOS development
animated GIF
Swift programming
UIImageView
mobile app development

Display animated GIF in iOS

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Displaying an animated GIF in iOS is possible, but it is not as automatic as loading a PNG into UIImageView. A GIF is a sequence of frames with timing metadata, so you either need to decode those frames yourself or use a library that handles decoding, caching, and playback efficiently.

Small Local GIFs With ImageIO

For bundled assets or small files, ImageIO gives you enough control to load frames and create an animated UIImage.

swift
1import UIKit
2import ImageIO
3
4func animatedImage(named name: String) -> UIImage? {
5    guard
6        let url = Bundle.main.url(forResource: name, withExtension: "gif"),
7        let source = CGImageSourceCreateWithURL(url as CFURL, nil)
8    else {
9        return nil
10    }
11
12    let frameCount = CGImageSourceGetCount(source)
13    var images: [UIImage] = []
14    var duration: TimeInterval = 0
15
16    for index in 0..<frameCount {
17        guard let cgImage = CGImageSourceCreateImageAtIndex(source, index, nil) else {
18            continue
19        }
20
21        images.append(UIImage(cgImage: cgImage))
22        duration += 0.1
23    }
24
25    return UIImage.animatedImage(with: images, duration: duration)
26}
27
28let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
29imageView.image = animatedImage(named: "loading")

This works, but it uses a simplified timing model. Real GIF files store per-frame delays, and a production-quality loader should read them from the image properties rather than assuming 0.1 seconds for every frame.

Respecting Frame Durations

Here is a more accurate version that reads the frame delay from GIF metadata.

swift
1import UIKit
2import ImageIO
3
4func frameDuration(from source: CGImageSource, at index: Int) -> TimeInterval {
5    guard
6        let properties = CGImageSourceCopyPropertiesAtIndex(source, index, nil) as? [CFString: Any],
7        let gif = properties[kCGImagePropertyGIFDictionary] as? [CFString: Any]
8    else {
9        return 0.1
10    }
11
12    let unclamped = gif[kCGImagePropertyGIFUnclampedDelayTime] as? Double
13    let clamped = gif[kCGImagePropertyGIFDelayTime] as? Double
14    let delay = unclamped ?? clamped ?? 0.1
15
16    return delay < 0.02 ? 0.1 : delay
17}

Using actual frame timing makes the animation look much closer to the original file.

When a Third-Party Library Is the Better Choice

For large GIFs, remote GIFs, or feeds with many animated images, manual frame loading is often not enough. Decoding every frame up front can use a lot of memory and cause janky scrolling.

In those cases, a library such as SDWebImage, Kingfisher with animated image support, or FLAnimatedImage is usually the better option. These libraries handle caching, background decoding, memory pressure, and network loading more gracefully than a small utility method.

An example with SDWebImage looks like this:

swift
1import UIKit
2import SDWebImage
3
4let imageView = SDAnimatedImageView()
5let url = URL(string: "https://example.com/demo.gif")
6imageView.sd_setImage(with: url)

That is much simpler than building a full remote GIF pipeline yourself.

UIKit and SwiftUI Considerations

In UIKit, UIImageView works for small, in-memory animations once you provide an animated UIImage. In SwiftUI, there is no built-in GIF view, so developers often wrap a UIKit view or use a library with SwiftUI support.

If the animation is decorative and loops forever, a short video or Lottie animation may be a better asset format than GIF. GIFs are widely supported, but they are not the most efficient choice for battery life or file size.

Common Pitfalls

The biggest mistake is loading a GIF with plain UIImage(named:) and expecting animation. That usually gives you only the first frame.

Another problem is decoding large GIFs on the main thread. Even if the result eventually displays, the app may hitch during scrolling or screen transitions.

Developers also underestimate memory usage. Building an animated UIImage from many full-resolution frames means all of those decoded images may sit in memory at once. That is fine for a small loading indicator and much less fine for a full-screen social feed.

Finally, GIF timing can be tricky. Ignoring frame delays produces animations that look too fast or inconsistent with the source file.

Summary

  • iOS can display animated GIFs, but you need to decode frames intentionally.
  • 'ImageIO works well for small local GIFs and gives you frame-level control.'
  • Reading real frame durations produces more accurate playback.
  • For large or remote GIFs, use a library built for animated image performance.
  • Consider whether GIF is the right asset format before adding it broadly across an app.

Course illustration
Course illustration

All Rights Reserved.