2015-01-22 10:54:27 +00:00
|
|
|
import Runes
|
2015-01-23 00:02:08 +00:00
|
|
|
import UIKit
|
2015-01-22 10:54:27 +00:00
|
|
|
|
2015-01-23 00:02:08 +00:00
|
|
|
/// A subclass of `UIImageView` that can be animated using an image name string or raw data.
|
2015-06-04 23:24:34 +00:00
|
|
|
public class AnimatableImageView: UIImageView {
|
2015-01-23 00:02:08 +00:00
|
|
|
/// An `Animator` instance that holds the frames of a specific image in memory.
|
2015-06-04 23:36:47 +00:00
|
|
|
private var animator: Animator?
|
2015-06-04 23:24:34 +00:00
|
|
|
/// A display link that keeps calling the `updateFrame` method on every screen refresh.
|
|
|
|
private lazy var displayLink: CADisplayLink = CADisplayLink(target: self, selector: Selector("updateFrame"))
|
2015-01-22 10:54:27 +00:00
|
|
|
|
2015-06-04 23:36:47 +00:00
|
|
|
/// The size of the frame cache.
|
|
|
|
public var framePreloadCount = 50
|
2015-06-04 19:38:52 +00:00
|
|
|
|
2015-01-23 00:02:08 +00:00
|
|
|
/// A computed property that returns whether the image view is animating.
|
2015-01-22 10:54:27 +00:00
|
|
|
public var isAnimatingGIF: Bool {
|
2015-06-04 23:24:34 +00:00
|
|
|
return !displayLink.paused
|
2015-01-22 10:54:27 +00:00
|
|
|
}
|
|
|
|
|
2015-01-23 00:02:08 +00:00
|
|
|
/// Prepares the frames using a GIF image file name, without starting the animation.
|
|
|
|
/// The file name should include the `.gif` extension.
|
|
|
|
///
|
|
|
|
/// :param: imageName The name of the GIF file. The method looks for the file in the app bundle.
|
2015-01-22 10:54:27 +00:00
|
|
|
public func prepareForAnimation(imageNamed imageName: String) {
|
|
|
|
let path = NSBundle.mainBundle().bundlePath.stringByAppendingPathComponent(imageName)
|
|
|
|
prepareForAnimation <^> NSData(contentsOfFile: path)
|
|
|
|
}
|
|
|
|
|
2015-01-23 00:02:08 +00:00
|
|
|
/// Prepares the frames using raw GIF image data, without starting the animation.
|
|
|
|
///
|
|
|
|
/// :param: data GIF image data.
|
2015-01-22 10:54:27 +00:00
|
|
|
public func prepareForAnimation(imageData data: NSData) {
|
|
|
|
image = UIImage(data: data)
|
2015-06-04 23:36:47 +00:00
|
|
|
animator = Animator(data: data, size: frame.size, contentMode: contentMode, framePreloadCount: framePreloadCount)
|
|
|
|
animator?.prepareFrames()
|
2015-06-04 23:24:34 +00:00
|
|
|
attachDisplayLink()
|
2015-01-22 10:54:27 +00:00
|
|
|
}
|
|
|
|
|
2015-01-23 00:02:08 +00:00
|
|
|
/// Prepares the frames using a GIF image file name and starts animating the image view.
|
|
|
|
///
|
|
|
|
/// :param: imageName The name of the GIF file. The method looks for the file in the app bundle.
|
2015-01-22 10:54:27 +00:00
|
|
|
public func animateWithImage(named imageName: String) {
|
|
|
|
prepareForAnimation(imageNamed: imageName)
|
|
|
|
startAnimatingGIF()
|
|
|
|
}
|
|
|
|
|
2015-01-23 00:02:08 +00:00
|
|
|
/// Prepares the frames using raw GIF image data and starts animating the image view.
|
|
|
|
///
|
|
|
|
/// :param: data GIF image data.
|
2015-01-22 10:54:27 +00:00
|
|
|
public func animateWithImageData(#data: NSData) {
|
|
|
|
prepareForAnimation(imageData: data)
|
|
|
|
startAnimatingGIF()
|
|
|
|
}
|
|
|
|
|
2015-01-23 00:02:08 +00:00
|
|
|
/// Updates the `UIImage` property of the image view if necessary. This method should not be called manually.
|
2015-01-22 10:54:27 +00:00
|
|
|
override public func displayLayer(layer: CALayer!) {
|
2015-02-10 19:07:54 +00:00
|
|
|
image = animator?.currentFrame
|
2015-01-22 10:54:27 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 23:24:34 +00:00
|
|
|
/// Update the current frame with the displayLink duration
|
|
|
|
func updateFrame() {
|
|
|
|
if animator?.updateCurrentFrame(displayLink.duration) ?? false {
|
|
|
|
layer.setNeedsDisplay()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-23 00:02:08 +00:00
|
|
|
/// Starts the image view animation.
|
2015-01-22 10:54:27 +00:00
|
|
|
public func startAnimatingGIF() {
|
2015-06-04 23:24:34 +00:00
|
|
|
if animator?.isAnimatable ?? false {
|
|
|
|
displayLink.paused = false
|
|
|
|
}
|
2015-01-22 10:54:27 +00:00
|
|
|
}
|
|
|
|
|
2015-01-23 00:02:08 +00:00
|
|
|
/// Stops the image view animation.
|
2015-01-22 10:54:27 +00:00
|
|
|
public func stopAnimatingGIF() {
|
2015-06-04 23:24:34 +00:00
|
|
|
displayLink.paused = true
|
2015-01-22 10:54:27 +00:00
|
|
|
}
|
2015-06-04 19:38:52 +00:00
|
|
|
|
2015-06-04 23:36:47 +00:00
|
|
|
/// Invalidate the displayLink so it releases this object.
|
2015-06-04 19:38:52 +00:00
|
|
|
public func cleanup() {
|
2015-06-04 23:36:47 +00:00
|
|
|
displayLink.invalidate()
|
2015-06-04 19:38:52 +00:00
|
|
|
}
|
2015-06-04 23:24:34 +00:00
|
|
|
|
2015-06-04 23:36:47 +00:00
|
|
|
/// Attaches the display link.
|
|
|
|
private func attachDisplayLink() {
|
|
|
|
displayLink.addToRunLoop(.mainRunLoop(), forMode: NSRunLoopCommonModes)
|
2015-06-04 23:24:34 +00:00
|
|
|
}
|
2015-01-22 10:54:27 +00:00
|
|
|
}
|
|
|
|
|