High-performance animated GIF support for iOS in Swift

Overview

Logo

Test GitHub release Carthage compatible Swift 5.0 platforms

Gifu adds protocol-based, performance-aware animated GIF support to UIKit. (It's also a prefecture in Japan).

Install

Swift Package Manager

Add the following to your Package.switft file:

let package = Package(
    dependencies: [
    .package(url: "https://github.com/kaishin/Gifu.git", from: "3.2.2")
    ],
)

Carthage

  • Add the following to your Cartfile: github "kaishin/Gifu"
  • Then run carthage update
  • Follow the current instructions in Carthage's README for up to date installation instructions.

CocoaPods

  • Add the following to your Podfile: pod 'Gifu'
  • You will also need to make sure you're opting into using frameworks: use_frameworks!
  • Then run pod install with CocoaPods 0.36 or newer.

How It Works

Gifu does not require using the built-in GIFImageView subclass. The Animator class does the heavy-lifting, while the GIFAnimatable protocol exposes the functionality to the view classes that conform to it, using protocol extensions.

The Animator has a FrameStore that only keeps a limited number of frames in-memory, effectively creating a buffer for the animation without consuming all the available memory. This approach makes loading large GIFs a lot more resource-friendly.

The figure below summarizes how this works in practice. Given an image containing 10 frames, Gifu will load the current frame (red), buffer the next two frames in this example (orange), and empty up all the other frames to free up memory (gray):

Usage

There are two options that should cover any situation:

  • Use the built-in GIFImageView subclass if you don't need to combine GIF support with another image library.
  • If you need more flexibility and composability, make your class conform to GIFAnimatable. In practice, any UIView subclass would do, since you get most of the required properties for free. For best results, make your UIImageView subclass conform to GIFAnimatable to get access to other features such as intrinsic content size.

GIFAnimatable

The bread and butter of Gifu. Through protocol extensions, GIFAnimatable exposes all the APIs of the library, and with very little boilerplate, any class can conform to it.

class MyImageView: UIImageView, GIFAnimatable {
  public lazy var animator: Animator? = {
    return Animator(withDelegate: self)
  }()

  override public func display(_ layer: CALayer) {
    updateImageIfNeeded()
  }
}

That's it. Now MyImageView has access to all these methods and properties:

  • prepareForAnimation(withGIFNamed:) and prepareForAnimation(withGIFData:) to prepare the animator property for animation.
  • startAnimatingGIF() and stopAnimatingGIF() to control the animation.
  • animate(withGIFNamed:) and animate(withGIFData:) to prepare for animation and start animating immediately.
  • frameCount, isAnimatingGIF, and activeFrame to inspect the GIF view.
  • prepareForReuse() to free up resources.
  • updateImageIfNeeded() to update the image property if necessary.

Furthermore, you can make any class GIF-animatable, starting with UIView subclasses:

class CustomAnimatedView: UIView, GIFAnimatable {
  public lazy var animator: Animator? = {
    return Animator(withDelegate: self)
  }()

  override public func display(_ layer: CALayer) {
    updateImageIfNeeded()
  }
}

You can also make UIKit classes conform using associated objects may you wish:

import UIKit
import Gifu

extension UIImageView: GIFAnimatable {
  private struct AssociatedKeys {
    static var AnimatorKey = "gifu.animator.key"
  }

  override open func display(_ layer: CALayer) {
    updateImageIfNeeded()
  }

  public var animator: Animator? {
    get {
      guard let animator = objc_getAssociatedObject(self, &AssociatedKeys.AnimatorKey) as? Animator else {
        let animator = Animator(withDelegate: self)
        self.animator = animator
        return animator
      }

      return animator
    }

    set {
      objc_setAssociatedObject(self, &AssociatedKeys.AnimatorKey, newValue as Animator?, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }
  }
}

Examples

The simplest way to get started is initializing a GIFAnimatable class in code or in a storyboard, then calling animate(:) on it.

let imageView = GIFImageView(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
imageView.animate(withGIFNamed: "mugen") {
  print("It's animating!")
}

You can also prepare for the animation when the view loads and only start animating after a user interaction.

// In your view controller..

override func viewDidLoad() {
  super.viewDidLoad()
  imageView.prepareForAnimation(withGIFNamed: "mugen") {
    print("Ready to animate!")
  }
}

@IBAction func toggleAnimation(_ sender: AnyObject) {
  if imageView.isAnimatingGIF {
    imageView.stopAnimatingGIF()
  } else {
    imageView.startAnimatingGIF()
  }
}

If you are using a GIFAnimatable class in a table or collection view, you can call the prepareForReuse() method in your cell subclass:

override func prepareForReuse() {
  super.prepareForReuse()
  imageView.prepareForReuse()
}

Demo App

Clone or download the repository and open Gifu.xcworkspace to check out the demo app.

Documentation

See the full API documentation.

Compatibility

  • iOS 9.0+
  • Swift 4.0
  • Xcode 9.0

License

See LICENSE.

Comments
  • iOS 14 GIFAnimatable UIKit extension doesn't play GIF

    iOS 14 GIFAnimatable UIKit extension doesn't play GIF

    I have updated to the newest version of the library after noticing GIF's were no longer playing on iOS 14, but the issue persists with the implementation I use, which is basically the UIKit extension from: https://github.com/kaishin/Gifu#gifanimatable.

    I have also replicated the fix that is implemented in the library itself in the extension, but to no avail.

        override open func display(_ layer: CALayer) {
            if UIImageView.instancesRespond(to: #selector(display(_:))) {
                super.display(layer)
            }
            updateImageIfNeeded()
        }
    
    opened by RemyLivewall 24
  • Having an issue switching from normal image to Gif

    Having an issue switching from normal image to Gif

    Until the release of Gifu 2.0 I had been using the old Swift 2.3 branch and it's worked for my needs. However, I just converted my codebase to Swift 3 and have been having issues. I am trying to switch an image in a GIFImageView from a .png to a .gif, it worked fine before but now it is not and I haven't been able to figure out why.

    prepareForReuse() was crashing the app. I tried two different things that stopped the crash but still wouldn't change the image. The first thing I tried was going to the stopAnimation() function and putting an animatable check similar to startAnimation(), this stopped the crashing but wouldn't update the image. Second I went to the GIFAnimatable class and put animator = nil in the prepareForReuse() function (mimicking the old codebase). This produced the same results as the first attempt.

    My code is as follows:

    mainImage: UIImage! 
    
    func changeImage(_ sender: UISegmentedControl) {
        switch sender.selectedSegmentIndex {
        case 1:
            imageView.prepareForReuse()
            imageView.animate(withGIFNamed: "\(name).gif")
        case 0:
            imageView.prepareForReuse()
            imageView.image = mainImage
        default:
            imageView.prepareForReuse()
            imageView.image = mainImage
        }
    }
    

    I'm not sure if there is a bug, missing functionality, or I am doing something wrong but as I said this works with the Swift 2.3 branch. Any help is appreciated, thank you.

    opened by chickdan 10
  • UIView animated being called from a background thread. Performing any operation from a background thread on UIView or a subclass is not supported and may result in unexpected and insidious behavior.

    UIView animated being called from a background thread. Performing any operation from a background thread on UIView or a subclass is not supported and may result in unexpected and insidious behavior.

    @kaishin @maicki @nicktoumpelis @izqui @mbcharbonneau

    I'm facing issue when i use GIF player in SceneKit please check below question for details->

    https://stackoverflow.com/questions/60507447/playing-gif-using-gifu-library-in-scenekit-causes-app-ui-freeze-any-solution-ui

    missing info 
    opened by MIOSY 8
  • Somehow Gifu memory address not being deallocated

    Somehow Gifu memory address not being deallocated

    I'm profiling an application, and found out several Gifu memory addresses that are still allocated even when I already stopped the animation and made the AnimatableImageView instance nil.

    screen shot 2016-06-02 at 7 38 36 pm

    It has become a bigger memory leak in my application since it's wasting almost half of what my app is actually using for its purposes.

    Any further information I can provide, I will be aware.

    Thanks in advance.

    opened by zheref 8
  • SwiftPM Package Resolution Failed for v3.3

    SwiftPM Package Resolution Failed for v3.3

    Swift Package Manager doesn't seem to be picking up the newest version of Gifu, causing package resolution to fail if you try to update to v3.3.

    because no versions of Gifu match the requirement 3.3.0..<4.0.0 and root depends on Gifu 3.3.0..<4.0.0, version solving failed.

    opened by colemcampbell 7
  • Can't use library with Swift 3

    Can't use library with Swift 3

    I use this pod line in my pods file: pod 'Gifu'

    Issues after Edit -> convert to current Swift version:

    1. Method does not override any method from its superclass error.
    override open func displayLayer(_ layer: CALayer) { 
      image = animator?.currentFrameImage ?? image
    }
    
    1. Contextual member 'main' has no associated value error
    func attachDisplayLink() {
      displayLink.add(to: .main(), forMode: RunLoopMode.commonModes)
    }
    
    opened by matrosovDev 7
  • Bad scrolling performance

    Bad scrolling performance

    I installed this late last night and wanted to see how it matched up against FLAnimatedImage. Not sure if this has anything to do with my particular setup but the scrolling performance was very "jittery". Sometimes it was smooth, other times the scroll motion would get stuck for a second and then become unstuck.

    For my setup I had a collection view with a with a Gifu image view in each cell. When not scrolling, I was very impressed with the low CPU and memory usage so congrats on that, but it seems like special adjustments need to be made to accommodate scrolling.

    opened by mitchellporter 7
  • GIFImageView: add missing call to super

    GIFImageView: add missing call to super

    Building my app in Xcode 12 beta 1, I noticed that none of my images were appearing.

    I found that this call to super in display(_ layer: CALayer) is important in iOS 14 - and suspect it is probably safe/good to have in previous versions too.

    opened by jverdi 6
  • Swift3 animate(withGIFData:) crash

    Swift3 animate(withGIFData:) crash

    Here's my call

    if let data = NSData(contentsOf: file.url.path) as? Data, file.url.lastPathComponent.contains(".gif"){
                 >>>>> iv.animate(withGIFData: data)
    }
    

    And this is where the crash is pointing to

    screen shot 2016-10-10 at 7 06 10 pm missing info 
    opened by iantheparker 6
  • Carthage: Parse error: expected submodule commit SHA in output of task (ls-tree -z v1.2.1 Carthage/Checkouts/Runes) but encountered:

    Carthage: Parse error: expected submodule commit SHA in output of task (ls-tree -z v1.2.1 Carthage/Checkouts/Runes) but encountered:

    While using Carthage to install the library, I got the output:

    $ carthage update --verbose
    *** Fetching Gifu
    *** Checking out Gifu at "v1.2.1"
    Parse error: expected submodule commit SHA in output of task (ls-tree -z v1.2.1 Carthage/Checkouts/Runes) but encountered: 
    

    I fixed this issue by cleaning up /Carthage/Checkouts/ and running $ carthage update --use-submodules

    Probably the README has to be updated.

    Carthage version is 0.17.2

    opened by evgeniyd 6
  • Move an animation to a specific frame

    Move an animation to a specific frame

    moveToFrame public function makes it possible to move an animation to a required GIF frame. It works according to the following algorithm:

    1. Stop currently played animation;
    2. Extract GIF frame in accordance with the given index;
    3. Display this frame;
    4. Rebuild the cache (animatedFrames array) during the next animation starting procedure.
    enhancement 
    opened by stanmots 6
  • Spurious console logs related to zero-sized imaging

    Spurious console logs related to zero-sized imaging

    In Xcode 14, we were receiving non-stop logs related to zero-sized imaging, which prevents the developer from using the console for appropriate debugging purposes.

    opened by syedfa 1
  • Don't attempt to resize zero-size frame images.

    Don't attempt to resize zero-size frame images.

    We were seeing a lot of spurious console logs related to zero-size image resizing. I added code to skip the resize if the target size is zero, and this fixed the issue.

    opened by syedfa 0
  • Add loopBlock callback for when a loop is finished

    Add loopBlock callback for when a loop is finished

    It's called every time the last frame is shown, on every loop. This is different to animationBlock which is only called after all the loops have finished (and never for infinite loops).

    Why? I have a use case where I'm playing a GIF in an infinite loop but I want to know when it has been shown at least once (first loop has been completed).

    Currently, there's no good way to satisfy this use case. One way is to read loopDuration and then schedule a timer to fire when that time has elapsed, which is roughly when one loop has happened. But in addition to being inaccurate, it's very fiddly because the timer has to be paused/unpaused if the GIF is paused/unpaused.

    Another way you might think would work is to use loopCount: 1 instead and then use animationBlock. Then there just start playback again for the rest of the loops. The problem with that is that there's no way to restart without preparing the frames again AFAICT.

    With this new callback, it's very straightforward.

    opened by robinst 1
  • Gifu animate method not displaying gif

    Gifu animate method not displaying gif

    I am unable to display the gif value when calling animate on GIFImageView, here is a more detailed post of the issue https://stackoverflow.com/questions/72417169/gifu-not-showing-image

    opened by Camelot93 0
  • Support other image formats

    Support other image formats

    I suggest adding an option to extend the framework to add other image decoders, e.g. WebP, APNG. Most of the display logic can be presumably reused across the formats.

    There were attempts to extend FLAnimatedImage to support additional formats, but none of them got merged. I don't know if there exists a framework that does these things without also bundling a massive image loading and caching library with it.

    feature request 
    opened by kean 1
  • Static GIF Image not show properly

    Static GIF Image not show properly

    If you would like to display a static GIF Image(only 1 frame), the first frame is not added to the image. Also due to it's a static image, it can't be showed by the startAnimatingGIF() function.

    There are two ways to show it, use GIFAnimatable's prepareForAnimation(withGIFData:loopCount:completionHandler:) or use other prepareForAnimation then call the updateImageIfNeeded().

    I think maybe other function start with prepareForAnimation should also add code like imageContainer.image = UIImage(data: imageData) or the trick which is mentioned above should be added to the documentation.

    feature request 
    opened by ruby109 1
Releases(v3.3.1)
Owner
Reda Lemeden
Developer/Designer based in Stockholm.
Reda Lemeden
An animated gif & apng engine for iOS in Swift. Have a great performance on memory and cpu usage.

Features Small but complete, only200lines of code. Allow to control display quality, memory usage, loop time and display progress. Have a great perfor

Jiawei Wang 1k Nov 9, 2022
Complete Animated GIF Support for iOS, with Functions, NSJSONSerialization-style Class, and (Optional) UIImage Swizzling

AnimatedGIFImageSerialization This library is no longer maintained. In iOS 13+ and macOS 10.15+, use CGAnimateImageAtURLWithBlock instead. AnimatedGIF

Mattt 1.1k Sep 29, 2022
Async GIF image decoder and Image viewer supporting play GIF images. It just use very less memory.

YLGIFImage Asynchronized GIF image class and Image viewer supporting play/stop GIF images. It just use very less memory. Following GIF usually will co

Yong Li 1.8k Aug 15, 2022
XAnimatedImage is a performant animated GIF engine for iOS written in Swift based on FLAnimatedImage

XAnimatedImage is a performant animated GIF engine for iOS written in Swift based on FLAnimatedImage. An illustration is shown below: Features Plays m

Khaled Taha 561 Sep 9, 2022
High performance and delightful way to play with APNG format in iOS.

APNGKit is a high performance framework for loading and displaying APNG images in iOS and macOS. It's built with high-level abstractions and brings a

Wei Wang 2.1k Jan 2, 2023
Performant animated GIF engine for iOS

FLAnimatedImage is a performant animated GIF engine for iOS: Plays multiple GIFs simultaneously with a playback speed comparable to desktop browsers H

Flipboard 7.8k Dec 29, 2022
Image framework for iOS to display/encode/decode animated WebP, APNG, GIF, and more.

YYImage Image framework for iOS to display/encode/decode animated WebP, APNG, GIF, and more. (It's a component of YYKit) Features Display/encode/decod

null 1.7k Dec 9, 2022
🌠 A small UIImage extension with gif support

?? A small UIImage extension with gif support

SwiftGif 1.3k Dec 20, 2022
Convert live photos and videos into animated GIFs in iOS, or extract frames from them.

Create a GIF from the provided video file url, Or extract images from videos. This repository has been separated from original repo along with some no

gitmerge 83 May 18, 2022
Test2 - A curated list of Open Source example iOS apps developed in Swift

Example iOS Apps A curated list of Open Source example iOS apps developed in Swi

null 0 Jan 4, 2022
Captcha implementation in ios App

CaptchaDemo_ios A Swift project to showcase implementation of Google ReCaptcha in iOS Application. Features A light weight basic wrapper to handle com

Tanvi jain 1 Feb 7, 2022
iOS implementation of the Catrobat language

Catty Catty, also known as Pocket Code for iOS, is an on-device visual programming system for iPhones. Catrobat is a visual programming language and s

null 74 Dec 25, 2022
High-performance animated GIF support for iOS in Swift

Gifu adds protocol-based, performance-aware animated GIF support to UIKit. (It's also a prefecture in Japan). Install Swift Package Manager Add the fo

Reda Lemeden 2.8k Jan 4, 2023
Gifu adds protocol-based, performance-aware animated GIF support to UIKit.

Gifu adds protocol-based, performance-aware animated GIF support to UIKit. (It's also a prefecture in Japan). Install Swift Package Manager Add the fo

Reda Lemeden 2.8k Jan 7, 2023
🔥 🔥 🔥Support for ORM operation,Customize the PQL syntax for quick queries,Support dynamic query,Secure thread protection mechanism,Support native operation,Support for XML configuration operations,Support compression, backup, porting MySQL, SQL Server operation,Support transaction operations.

?? ?? ??Support for ORM operation,Customize the PQL syntax for quick queries,Support dynamic query,Secure thread protection mechanism,Support native operation,Support for XML configuration operations,Support compression, backup, porting MySQL, SQL Server operation,Support transaction operations.

null 60 Dec 12, 2022
High performance GIF engine

SwiftyGif High performance & easy to use Gif engine Features UIImage and UIImageView extension based Remote GIFs with customizable loader Great CPU/Me

Alexis Creuzot 1.7k Jan 3, 2023
SwiftyGif - High performance & easy to use Gif engine

SwiftyGif High performance & easy to use Gif engine Features UIImage and UIImageView extension based Remote GIFs with customizable loader Great CPU/Me

Alexis Creuzot 1.7k Jan 3, 2023
An animated gif & apng engine for iOS in Swift. Have a great performance on memory and cpu usage.

Features Small but complete, only200lines of code. Allow to control display quality, memory usage, loop time and display progress. Have a great perfor

Jiawei Wang 1k Nov 9, 2022
Complete Animated GIF Support for iOS, with Functions, NSJSONSerialization-style Class, and (Optional) UIImage Swizzling

AnimatedGIFImageSerialization This library is no longer maintained. In iOS 13+ and macOS 10.15+, use CGAnimateImageAtURLWithBlock instead. AnimatedGIF

Mattt 1.1k Sep 29, 2022
Async GIF image decoder and Image viewer supporting play GIF images. It just use very less memory.

YLGIFImage Asynchronized GIF image class and Image viewer supporting play/stop GIF images. It just use very less memory. Following GIF usually will co

Yong Li 1.8k Aug 15, 2022