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.
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.swiftfile:Carthage
github "kaishin/Gifu"carthage updateCocoaPods
pod 'Gifu'use_frameworks!pod installwith CocoaPods 0.36 or newer.How It Works
Gifudoes not require using the built-inGIFImageViewsubclass. TheAnimatorclass does the heavy-lifting, while theGIFAnimatableprotocol exposes the functionality to the view classes that conform to it, using protocol extensions.The
Animatorhas aFrameStorethat 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:
GIFImageViewsubclass if you don’t need to combine GIF support with another image library.GIFAnimatable. In practice, anyUIViewsubclass would do, since you get most of the required properties for free. For best results, make yourUIImageViewsubclass conform toGIFAnimatableto get access to other features such as intrinsic content size.GIFAnimatable
The bread and butter of Gifu. Through protocol extensions,
GIFAnimatableexposes all the APIs of the library, and with very little boilerplate, any class can conform to it.That’s it. Now
MyImageViewhas access to all these methods and properties:prepareForAnimation(withGIFNamed:)andprepareForAnimation(withGIFData:)to prepare the animator property for animation.startAnimatingGIF()andstopAnimatingGIF()to control the animation.animate(withGIFNamed:)andanimate(withGIFData:)to prepare for animation and start animating immediately.frameCount,isAnimatingGIF, andactiveFrameto 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
UIViewsubclasses:You can also make
UIKitclasses conform using associated objects may you wish:Examples
The simplest way to get started is initializing a
GIFAnimatableclass in code or in a storyboard, then callinganimate(:)on it.You can also prepare for the animation when the view loads and only start animating after a user interaction.
If you are using a
GIFAnimatableclass in a table or collection view, you can call theprepareForReuse()method in your cell subclass:Demo App
Clone or download the repository and open
Demo/Demo.xcworkspaceto check out the demo app.Documentation
See the full API documentation.
Compatibility
License
See LICENSE.