Gifu adds protocol-based, performance-aware animated GIF support to UIKit, without forcing you to use a UIImageView
subclass. (It’s also a prefecture in Japan).
⚠ Swift 2.3 support is on the swift2.3 branch. This branch will not be getting any future updates.
Install
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 rely on subclassing UIImageView
. 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. - Make
UIImageView
or any of its subclasses conform toGIFAnimatable
.
GIFImageView
A subclass of UIImageView
that conforms to GIFAnimatable
. You can use this class as-is or subclass it for further customization (not recommended).
GIFAnimatable
The bread and butter of Gifu. Through protocol extensions, GIFAnimatable
exposes all the APIs of the library, and with very little boilerplate, any UIImageView
subclass 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
is fully GIF-compatible, and any of these methods can be called on it:
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
, andactiveFrame
to inspect the GIF view.prepareForReuse()
to free up resources.updateImageIfNeeded()
to update the image property if necessary.
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")
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")
}
@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 3.0
- Xcode 8.0
License
See LICENSE.