-[![GitHub release](https://img.shields.io/github/release/kaishin/Gifu.svg?maxAge=2592000)](https://github.com/kaishin/Gifu/releases/latest) [![Travis](https://travis-ci.org/kaishin/Gifu.svg?branch=master)](https://travis-ci.org/kaishin/Gifu) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Join the chat at https://gitter.im/kaishin/gifu](https://badges.gitter.im/kaishin/gifu.svg)](https://gitter.im/kaishin/gifu)
+[![GitHub release](https://img.shields.io/github/release/kaishin/Gifu.svg?maxAge=2592000)](https://github.com/kaishin/Gifu/releases/latest) [![Travis](https://travis-ci.org/kaishin/Gifu.svg?branch=master)](https://travis-ci.org/kaishin/Gifu) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Join the chat at https://gitter.im/kaishin/gifu](https://badges.gitter.im/kaishin/gifu.svg)](https://gitter.im/kaishin/gifu) ![Swift 3.0.x](https://img.shields.io/badge/Swift-3.0.x-orange.svg) ![platforms](https://img.shields.io/badge/platforms-iOS-lightgrey.svg)
-Adds performant animated GIF support to UIKit. If you're looking for the Japanese prefecture, click [here](https://goo.gl/maps/CCeAc).
-
-⚠ **Swift 3.0** support is in progress on the [swift3](https://github.com/kaishin/Gifu/tree/swift3) branch.
+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](https://goo.gl/maps/CCeAc)).
⚠ **Swift 2.3** support is on the [swift2.3](https://github.com/kaishin/Gifu/tree/swift2.3) branch. **This branch will not be getting any future updates**.
+## Install
-
-#### How?
-
-Gifu uses a `UIImageView` subclass and an animator that keeps track of frames and their durations.
-
-It uses `CADisplayLink` to animate the view and only keeps a limited number of
-resized frames in-memory, which exponentially minimizes memory usage for large GIF files (+300 frames).
-
-The figure below summarizes how this works in practice. Given an image
-containing 10 frames, Gifu will load the current frame (red), pre-load the next two frames in this example (orange), and nullify all the other frames to free up memory (gray):
-
-
-
-#### Install
-#### [Carthage](https://github.com/Carthage/Carthage)
+### [Carthage](https://github.com/Carthage/Carthage)
- Add the following to your Cartfile: `github "kaishin/Gifu"`
- Then run `carthage update`
@@ -32,40 +17,111 @@ for up to date installation instructions.
[carthage-installation]: https://github.com/Carthage/Carthage#adding-frameworks-to-an-application
-#### [CocoaPods](http://cocoapods.org)
+### [CocoaPods](http://cocoapods.org)
- Add the following to your [Podfile](http://guides.cocoapods.org/using/the-podfile.html): `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.
-#### Usage
+## 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
-Start by instantiating an `AnimatableImageView` either in code or Interface Builder, then call `animateWithImage(named:)` or `animateWithImageData(data:)` on it.
+There are two options that should cover any situation:
-```swift
-let imageView = AnimatableImageView(frame: CGRect(...))
-imageView.animateWithImage(named: "mugen.gif")
-```
-You can stop the animation anytime using `imageView.stopAnimatingGIF()`, and resume
-it using `imageView.startAnimatingGIF()`.
+- Use the built-in `GIFImageView` subclass.
+- Make `UIImageView` or any of its subclasses conform to `GIFAnimatable`.
-The `isAnimatingGIF()` method returns the current animation state of the view if it has an animatable image.
+### GIFImageView
-See the [full documentation](http://kaishin.github.io/Gifu/).
+A subclass of `UIImageView` that conforms to `GIFAnimatable`. You can use this class as-is or subclass it for further customization (not recommended).
-#### Demo App
+### 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.
+
+~~~swift
+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:)` 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.
+
+### Examples
+
+The simplest way to get started is initializing a `GIFAnimatable` class in code or in a storyboard, then calling `animate(:)` on it.
+
+~~~swift
+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.
+
+~~~swift
+// 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:
+
+~~~swift
+override func prepareForReuse() {
+ super.prepareForReuse()
+ imageView.prepareForReuse()
+}
+~~~
+
+### Demo App
Clone or download the repository and open `Gifu.xcworkspace` to check out the demo app.
-#### Compatibility
+## Documentation
+
+See the [full API documentation](http://kaishin.github.io/Gifu/).
-- iOS 8+
-#### Misc
+## Compatibility
-- The font used in the logo is [Azuki](http://www.myfonts.com/fonts/bluevinyl/azuki/)
-- The characters used in the icon and example image in the demo are from [Samurai Champloo](https://en.wikipedia.org/wiki/Samurai_Champloo).
+- iOS 9.0+
+- Swift 3.0
+- Xcode 8.0
-#### License
+## License
See LICENSE.
diff --git a/Source/Classes/GIFAnimatable.swift b/Source/Classes/GIFAnimatable.swift
index 26fe89b..f3a92f0 100644
--- a/Source/Classes/GIFAnimatable.swift
+++ b/Source/Classes/GIFAnimatable.swift
@@ -85,7 +85,8 @@ extension GIFAnimatable {
/// Updates the image with a new frame if necessary.
public func updateImageIfNeeded() {
- image = animator?.activeFrame() ?? image
+ let frame = animator?.activeFrame() ?? image
+ if image != frame { image = frame }
}
}
diff --git a/Supporting Files/Info.plist b/Supporting Files/Info.plist
index b355c11..f3ced5d 100644
--- a/Supporting Files/Info.plist
+++ b/Supporting Files/Info.plist
@@ -15,11 +15,11 @@
CFBundlePackageTypeFMWKCFBundleShortVersionString
- 1.2.1
+ 2.0CFBundleSignature????CFBundleVersion
- 124
+ 132NSPrincipalClass
diff --git a/docs/Classes.html b/docs/Classes.html
new file mode 100644
index 0000000..b437fae
--- /dev/null
+++ b/docs/Classes.html
@@ -0,0 +1,134 @@
+
+
+
+ Classes Reference
+
+
+
+
+
+
+
+
+
+
+
Example class that conforms to GIFAnimatable. Uses default values for the animator frame buffer count and resize behavior. You can either use it directly in your code or use it as a blueprint for your own subclass.
Example class that conforms to GIFAnimatable. Uses default values for the animator frame buffer count and resize behavior. You can either use it directly in your code or use it as a blueprint for your own subclass.
Example class that conforms to GIFAnimatable. Uses default values for the animator frame buffer count and resize behavior. You can either use it directly in your code or use it as a blueprint for your own subclass.
Example class that conforms to GIFAnimatable. Uses default values for the animator frame buffer count and resize behavior. You can either use it directly in your code or use it as a blueprint for your own subclass.
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.
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 to GIFAnimatable.
+
+
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.
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.
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 to GIFAnimatable.
+
+
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.