Upgrade to Pro — share decks privately, control downloads, hide ads and more …

High performance GIF playback/iOSDC25

Avatar for noppefoxwolf noppefoxwolf
September 25, 2025

High performance GIF playback/iOSDC25

Avatar for noppefoxwolf

noppefoxwolf

September 25, 2025
Tweet

More Decks by noppefoxwolf

Other Decks in Technology

Transcript

  1. Who am I noppe ! ‣ iOSDC Speaker (8 years)

    ‣ Senior iOS Developer at DeNA ‣ Indie App Developer 2
  2. DAWN for Mastodon My indie app for Mastodon ‣ Normal

    iOS design ‣ Animation images (GIF, APNG, WebP) ‣ High-performance scrolling ‣ Multi-instance support 3
  3. 4

  4. Decentralized social network ‣ Open-source platform (2016) ‣ Anyone can

    run a server ‣ Servers form federated network ‣ Compatible with Threads, Misskey 5
  5. Custom Emojis User-uploaded animated emojis ‣ Like Slack custom emojis

    ‣ Each server has unique collection ‣ GIF, APNG, WebP support ‣ Used in posts and reactions 7
  6. The Challenge Timeline filled with animated emojis ‣ Dozens of

    GIFs simultaneously ‣ Mixed formats & frame rates ‣ Performance nightmare ! 8 Beware of flashing lights / ఺໓ʹ͓ؾΛ͚͍ͭͩ͘͞
  7. 9

  8. DAWN's Solution ✅ Smooth scrolling with dozens of animated emojis

    ✅ Memory efficient rendering ✅ Support for GIF, APNG, WebP ✅ Responsive UI under heavy load 10
  9. Agenda 1. How to show GIF animation in UIKit. 2.

    How to improve performance. 11
  10. // try to show GIF image. let image = UIImage(named:

    "sample.gif") let imageView = UIImageView(image: image) view.addSubview(imageView) 13
  11. // Extract Frame Images // GIF, APNG, WEBP file let

    fileURL = ... let source = CGImageSourceCreateWithURL( fileURL as CFURL, nil ) let count = CGImageSourceGetCount(gifSource) var images: [UIImage] = [] for index in 0..<count { let cgImage = CGImageSourceCreateImageAtIndex( source, index, nil ) images.append(UIImage(cgImage: cgImage)) } 16
  12. 18

  13. Memory Usage Problem 340KB GIF = 25MB RAM! ‣ Same

    as 8K JPEG memory usage ‣ Exponential memory growth ‣ App crashes with multiple GIFs 19
  14. Memory Calculation Formula for memory usage: 480×400×4×34 = 25,958,400Byte ≈

    25MB ‣ W: Width in pixels (480) ‣ H: Height in pixels (400) ‣ C: Color (4 for ARGB) ‣ N: Number of frames (34) 20 8bit, ARGB image case
  15. 1. Identify User Pain Start with user experience ‣ What

    issues are users facing? ‣ Where do they struggle? ‣ What frustrates them? 23
  16. 2. Define Core Value What's your app's mission? ‣ What

    makes it irreplaceable? ‣ What would users miss most? 24
  17. 3. Measure Everything Quantify with profiling tools ‣ Use Instruments,

    Xcode ‣ Memory, CPU, frame rate ‣ Identify bottlenecks ‣ Evaluate improvements 25
  18. 4. Smart Trade-offs A puzzle of priorities ‣ Lower quality

    of unimportant things ‣ Raise quality of what matters 27
  19. 28

  20. 29

  21. AnimatedImage github.com/noppefoxwolf/AnimatedImage ‣ Specialized UIKit component for high-performance GIF playback

    ‣ Supports GIF, APNG, WebP formats ‣ Memory-efficient frame caching ‣ Background processing pipeline 30
  22. 31

  23. UIUpdateLink ! ‣ iOS17+ ‣ An object you use to

    observe, participate in, and affect the UI update process. // Update y every frame. let updateLink = UIUpdateLink(view: view) updateLink.addAction { link, info in // Code that runs each UI update, after processing input events, // but before `CADisplayLink` callbacks. self.view.center.y = sin(info.modelTime) * 100 + self.view.bounds.midY } 34
  24. 36

  25. 38

  26. 40

  27. 41

  28. 42

  29. Solution: Pre-decompress Decompress on background thread // UIKit let decompressedImage

    = await uiImage.byPreparingForDisplay() // CoreGraphics let context = CGContext(...)! context.draw(image, in: rect) let decodedImage = context.makeImage() 46
  30. 47

  31. 48

  32. Next steps ‣ Explore AnimatedImage features ‣ Try AnimatedImage in

    your projects ‣ Deep dive into WebP ࡞ֶͬͯͿWebPೖ໳ day1 13:00 Track A 49