Gifu adds protocol-based, performance-aware animated GIF support to UIKit.

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
Autocrop - A face-aware crop utility using OSX's Vision framework

autocrop A high-performance face-aware crop utility using OSX's Vision framework

Alex Dong 0 Jan 19, 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 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
SwiftGif - A small UIImage extension with gif support.

SwiftGif - A small UIImage extension with gif support.

SwiftGif 1.3k Dec 20, 2022
A tool support convert image gif to gif3d

Trick convert gif to gif3d using Swift Features Simple way to convert gif to gif3d Change background Change size eraser tool How to work Add a layer w

Chuong Tran 16 Jan 4, 2023
A Swift implementation of fastimage. Supports PNG, GIF, and JPEG.

ImageScout ImageScout is a Swift implementation of fastimage. It allows you to find the size and type of a remote image by downloading as little as po

Reda Lemeden 967 Dec 30, 2022
Drop in GIF Collection View. Uses Tenor as default GIFs provider.

Drop in GIF Collection View. Uses Tenor as default GIFs provider. This will allow you to easily integrate GIF image search into your app or you can use this as a GIF keyboard for your messaging needs.

null 5 May 7, 2022
DGImageView - Asynchronous image downloader with cache. Supports gif too

DGImageView Installation Usage DGImageView Asynchronous image downloader with cache. Supports gif, memory cache, disk cache features. Installation Xco

donggyu 1 Jan 1, 2022
An app show your Live Photo and export as GIF.

LivelyGIFs Show your Live Photo and export as GIF. Demo HighLights Do not use Pod or Cathage to install 3rd party library Simple logic, new learner fr

Xue Yu 95 Jun 24, 2022
Media view which subclasses UIImageView, and can display & load images, videos, GIFs, and audio and from the web, and has functionality to minimize from fullscreen, as well as show GIF previews for videos.

I've built out the Swift version of this library! Screenshots Description ABMediaView can display images, videos, as well as now GIFs and Audio! It su

Andrew Boryk 80 Dec 20, 2022
APNGKit is a high performance framework for loading and displaying APNG images in iOS and macOS.

APNGKit is a high performance framework for loading and displaying APNG images in iOS and macOS. It's built on top of a modified version of libpng wit

Wei Wang 2.1k Dec 30, 2022
An extremely high-performance, lightweight, and energy-efficient pure Swift async web image loader with memory and disk caching for iOS and  Watch.

KFSwiftImageLoader KFSwiftImageLoader is an extremely high-performance, lightweight, and energy-efficient pure Swift async web image loader with memor

Kiavash Faisali 343 Oct 29, 2022
A high-performance image library for downloading, caching, and processing images in Swift.

Features Asynchronous image downloader with priority queuing Advanced memory and database caching using YapDatabase (SQLite) Guarantee of only one ima

Yap Studios 72 Sep 19, 2022
A pure Swift high-performance asynchronous image loading framework. SwiftUI supported.

Longinus Longinus is a pure-Swift high-performance asynchronous web image loading,caching,editing framework. It was learned from Objective-C web image

Qitao Yang 290 Dec 17, 2022
A simplest & base on protocol & swifty way to browse photo or video with hero animation.

JFHeroBrowser Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements Installation JFHe

逸风 22 Dec 19, 2022
LoremPicsum - Simple UIKit based app for displaying grid of pictures

LoremPicsum - Simple UIKit based app for displaying grid of pictures

Paweł Dziennik 0 Jan 20, 2022
Animated sharingan loader for iOS projects.

Animated sharingan loader for iOS projects. This is a fun project created using SwiftUI with love for the Uchiha clan. More types of eyes to come with tons of customizations...

Manas Aggarwal 16 Nov 30, 2022
Easy customizable avatar image asynchronously with progress bar animated

JDSwiftAvatarProgress ##Objective-C JDAvatarProgress is available in Objective-C also, JDAvatarProgress Usage To run the example project, clone the re

Jelly Development 86 May 16, 2022
Fun GridScrollView written in SwiftUI + Combine, bridging between UIKit

BSZoomGridScrollView BSZoomGridScrollView is a powerful, pure swift iOS UI framework that provides the awesome grid scrollview containing your image a

Jang Seoksoon 148 Dec 17, 2022