Gifu为UIKit添加了基于协议、具有性能考量支持的动态GIF支持。(它也是日本的一个县)。
安装
Swift 包管理器
将以下内容添加到您的Package.swift
文件中
let package = Package(
dependencies: [
.package(url: "https://github.com/kaishin/Gifu.git", from: "3.2.2")
],
)
Carthage
- 将以下内容添加到您的Cartfile中:
github "kaishin/Gifu"
- 然后运行
carthage update
- 有关最新安装说明,请遵循Carthage的README中的当前说明。
CocoaPods
- 将以下内容添加到您的Podfile:
pod 'Gifu'
- 您还需要确保您启用使用框架:
use_frameworks!
- 然后使用 CocoaPods 0.36 或更高版本运行
pod install
。
工作原理
Gifu
不需要使用内置的 GIFImageView
子类。Animator
类负责重任,而 GIFAnimatable
协议通过协议扩展将功能暴露给遵循它的视图类。
Animator
有一个 FrameStore
,它仅在内存中保留有限数量的帧,有效地创建了一个用于动画的缓冲区,而不消耗所有可用内存。这种方法使加载大型 GIF 变得更加节省资源。
以下图表总结了实际情况如何工作。给定一个包含 10 帧的图像,Gifu 将加载当前帧(红色),在这个例子中缓冲下两个帧(橙色),并清除所有其他帧以释放内存(灰色)。
使用方法
有以下两种选项应该可以覆盖任何情况
- 如果不需将 GIF 支持与另一个图像库结合,请使用内置的
GIFImageView
子类。 - 如果您需要更多灵活性和可组合性,则使您的类符合
GIFAnimatable
。实际上,任何UIView
子类都可以,因为您会免费获得所需的大部分属性。为了获得最佳效果,请使您的UIImageView
子类符合GIFAnimatable
以获取其他功能,例如固有声内容大小。
GIFAnimatable
是 Gifu 的核心。通过协议扩展,GIFAnimatable
暴露了库的所有 API,并且可以非常少的样板代码,任何类都可以符合它。
class MyImageView: UIImageView, GIFAnimatable {
public lazy var animator: Animator? = {
return Animator(withDelegate: self)
}()
override public func display(_ layer: CALayer) {
updateImageIfNeeded()
}
}
就这样。现在 MyImageView
可以访问所有这些方法和属性
prepareForAnimation(withGIFNamed:)
和prepareForAnimation(withGIFData:)
用于为动画准备动画器属性。startAnimatingGIF()
和stopAnimatingGIF()
用于控制动画。animate(withGIFNamed:)
和animate(withGIFData:)
用于准备动画并立即开始播放。frameCount
、isAnimatingGIF
和activeFrame
用于检查 GIF 视图。prepareForReuse()
用于释放资源。updateImageIfNeeded()
用于在必要时更新图像属性。
此外,您可以从 UIView
子类开始,使任何类都能支持 GIF 动画。
class CustomAnimatedView: UIView, GIFAnimatable {
public lazy var animator: Animator? = {
return Animator(withDelegate: self)
}()
override public func display(_ layer: CALayer) {
updateImageIfNeeded()
}
}
您还可以通过关联对象使 UIKit
类遵守您希望的条件。
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)
}
}
}
示例
开始使用最简单的方式是初始化一个 GIFAnimatable
类,无论是在代码中还是在Storyboard中,然后对其调用 animate(:)
。
let imageView = GIFImageView(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
imageView.animate(withGIFNamed: "mugen") {
print("It's animating!")
}
您还可以在视图加载时准备动画,然后只在用户交互后启动动画。
// In your view controller..
override func viewDidLoad() {
super.viewDidLoad()
imageView.prepareForAnimation(withGIFNamed: "mugen") {
print("Ready to animate!")
}
}
@IBAction func toggleAnimation(_ sender: AnyObject) {
if imageView.isAnimatingGIF {
imageView.stopAnimatingGIF()
} else {
imageView.startAnimatingGIF()
}
}
如果您在一个表格或集合视图中使用 GIFAnimatable
类,您可以在您的单元格子类中调用 prepareForReuse()
方法。
override func prepareForReuse() {
super.prepareForReuse()
imageView.prepareForReuse()
}
示例应用
克隆或下载此仓库,然后打开 Gifu.xcworkspace
来查看示例应用。
文档
查看完整的 API 文档。
兼容性
- iOS 9.0+
- Swift 4.0
- Xcode 9.0
许可
请参阅 LICENSE。