Skip to content

Commit

Permalink
Update README and check-in docs
Browse files Browse the repository at this point in the history
- Closes #79
  • Loading branch information
Reda Lemeden committed Oct 6, 2016
1 parent 22397e9 commit 3ac44fe
Show file tree
Hide file tree
Showing 37 changed files with 4,013 additions and 42 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,3 @@ Carthage/Build

Gifu.framework.zip
*.xcscmblueprint
docs/
132 changes: 94 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,14 @@
# ![Gifu](https://db.tt/mZ1iMNXO)
<h1><img src="https://github.com/kaishin/Gifu/raw/swift3/header.gif" alt="Gifu Logo" style="border-radius: 6px"></h1>

[![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):

<img src="https://db.tt/ZLfx23hg" width="300" />

#### 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`
Expand All @@ -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):

<img src="https://db.tt/ZLfx23hg" width="300" />

## 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.
3 changes: 2 additions & 1 deletion Source/Classes/GIFAnimatable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
}
}

Expand Down
4 changes: 2 additions & 2 deletions Supporting Files/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.2.1</string>
<string>2.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>124</string>
<string>132</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
Expand Down
134 changes: 134 additions & 0 deletions docs/Classes.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Classes Reference</title>
<link rel="stylesheet" type="text/css" href="css/jazzy.css" />
<link rel="stylesheet" type="text/css" href="css/highlight.css" />
<meta charset='utf-8'>
<script src="js/jquery.min.js" defer></script>
<script src="js/jazzy.js" defer></script>

</head>
<body>
<a title="Classes Reference"></a>
<header>
<div class="content-wrapper">
<p><a href="index.html">Gifu Docs</a> (100% documented)</p>
<p class="header-right"><a href="https://github.com/kaishin/gifu/"><img src="img/gh.png"/>View on GitHub</a></p>
<p class="header-right"><a href="dash-feed://https%3A%2F%2Fpyroh%2Egithub%2Eio%2Fdocsets%2FGifu%2Exml"><img src="img/dash.png"/>Install in Dash</a></p>
</div>
</header>
<div class="content-wrapper">
<p id="breadcrumbs">
<a href="index.html">Gifu Reference</a>
<img id="carat" src="img/carat.png" />
Classes Reference
</p>
</div>
<div class="content-wrapper">
<nav class="sidebar">
<ul class="nav-groups">
<li class="nav-group-name">
<a href="Classes.html">Classes</a>
<ul class="nav-group-tasks">
<li class="nav-group-task">
<a href="Classes/Animator.html">Animator</a>
</li>
<li class="nav-group-task">
<a href="Classes/GIFImageView.html">GIFImageView</a>
</li>
</ul>
</li>
<li class="nav-group-name">
<a href="Protocols.html">Protocols</a>
<ul class="nav-group-tasks">
<li class="nav-group-task">
<a href="Protocols/GIFAnimatable.html">GIFAnimatable</a>
</li>
</ul>
</li>
</ul>
</nav>
<article class="main-content">
<section>
<section class="section">
<h1>Classes</h1>
<p>The following classes are available globally.</p>

</section>
<section class="section task-group-section">
<div class="task-group">
<ul>
<li class="item">
<div>
<code>
<a name="/s:C4Gifu12GIFImageView"></a>
<a name="//apple_ref/swift/Class/GIFImageView" class="dashAnchor"></a>
<a class="token" href="#/s:C4Gifu12GIFImageView">GIFImageView</a>
</code>
</div>
<div class="height-container">
<div class="pointer-container"></div>
<section class="section">
<div class="pointer"></div>
<div class="abstract">
<p>Example class that conforms to <code><a href="Protocols/GIFAnimatable.html">GIFAnimatable</a></code>. 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.</p>

<a href="Classes/GIFImageView.html" class="slightly-smaller">See more</a>
</div>
<div class="declaration">
<h4>Declaration</h4>
<div class="language">
<p class="aside-title">Swift</p>
<pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="kt">GIFImageView</span><span class="p">:</span> <span class="kt">UIImageView</span><span class="p">,</span> <span class="kt"><a href="Protocols/GIFAnimatable.html">GIFAnimatable</a></span></code></pre>

</div>
</div>
</section>
</div>
</li>
</ul>
</div>
<div class="task-group">
<ul>
<li class="item">
<div>
<code>
<a name="/s:C4Gifu8Animator"></a>
<a name="//apple_ref/swift/Class/Animator" class="dashAnchor"></a>
<a class="token" href="#/s:C4Gifu8Animator">Animator</a>
</code>
</div>
<div class="height-container">
<div class="pointer-container"></div>
<section class="section">
<div class="pointer"></div>
<div class="abstract">
<p>Responsible for parsing GIF data and decoding the individual frames.</p>

<a href="Classes/Animator.html" class="slightly-smaller">See more</a>
</div>
<div class="declaration">
<h4>Declaration</h4>
<div class="language">
<p class="aside-title">Swift</p>
<pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="kt">Animator</span></code></pre>

</div>
</div>
</section>
</div>
</li>
</ul>
</div>
</section>
</section>
<section id="footer">
<p>2015 © Reda Lemeden. See LICENSE for more details.</p>
<p>Generated by <a class="link" href="https://github.com/realm/jazzy" target="_blank" rel="external">jazzy ♪♫ v0.7.2</a>, a <a class="link" href="http://realm.io" target="_blank" rel="external">Realm</a> project.</p>
</section>
</article>
</div>
</body>
</div>
</html>
Loading

0 comments on commit 3ac44fe

Please sign in to comment.