轻量级、高性能、内存高效的 Gif 框架
功能
- 尊重 Gif 帧间隔
- 优化 CPU 和内存性能
- 考虑到 UITableViewCell 和 UICollectionViewCell 设计
- 完全控制所有细节,例如准备过程、动画质量、输出图像质量等...
- 可扩展且易于使用
安装
使用 CocoaPods
source 'https://cocoapods.org.cn/pods/JellyGif'
use_frameworks!
pod 'JellyGif'
用法
开始使用最简单的方法是使用 JellyGifImageView
并调用 startGif(with:)
。
import JellyGif
let imageView = JellyGifImageView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
//Animates Gif from the main bundle
imageView.startGif(with: .name("Gif name"))
//Animates Gif with a local path
let url = URL(string: "Gif path")!
imageView.startGif(with: .localPath(url))
//Animates Gif with data
imageView.startGif(with: .data(Data))
为了充分利用 JellyGif 的全部功能,请使用 JellyGifAnimator
并遵守它的 JellyGifAnimatorDelegate
。
import JellyGif
let imageView = UIImageView(CGRect(x: 0, y: 0, width: 100, height: 100))
let animator = JellyGifAnimator(imageInfo: .name("Gif name"), pixelSize: .custom(350), animationQuality: .best)
animator.delegate = self
//JellyGifAnimatorDelegate
func gifAnimatorIsReady(_ sender: JellyGifAnimator) {
sender.startAnimation()
}
func imageViewForAnimator(_ sender: JellyGifAnimator) -> UIImageView? {
return imageView
}
func gifAnimatorDidChangeImage(_ image: UIImage, sender: JellyGifAnimator) {
//Use this method if you want to manually update Gif frame instead of using an UIImageView
}
JellyGifAnimator
允您控制每个方面的 Gif,包括最大输出大小 - pixelSize
和每秒帧数 - animationQuality
。当 pixelSize
属性接近图像持有器的实际大小时,内存占用将更小,CPU 性能将更好。
UICollectionView & UITableView
要使用 JellyGifAnimator
与 UICollectionView
或 UITableView
,请在 UICollectionView
或 UITableView
的拥有者内部创建一个 JellyGifAnimator
字典,并符合 JellyGifAnimatorDelegate
import JellyGif
class ViewController: UIViewController {
var gifNames: [String] = []
var animators: [IndexPath: JellyGifAnimator] = [:]
//Your code
//...
}
extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
//Your Code
//...
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//dequeue cell
//...
let gifName = gifNames[indexPath.item]
if animators[indexPath] == nil {
let animator = JellyGifAnimator(imageInfo: .name(gifName), pixelSize: .custom(350), animationQuality: .best)
animators[indexPath] = animator
}
//If the Gif is not ready, show a placeholder image - which is the first frame of the Gif instead
if animators[indexPath]?.isReady != true {
cell.imageView.image = animators[indexPath]?.placeholder
}
animators[indexPath]?.delegate = self
return cell
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if animators[indexPath]?.isReady == true {
animators[indexPath]?.startAnimation()
} else {
animators[indexPath]?.prepareAnimation()
}
}
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
//Pause animation and the preparation process if the cell is not visible
animators[indexPath]?.pauseAnimation()
animators[indexPath]?.stopPreparingAnimation()
}
}
extension ViewController: JellyGifAnimatorDelegate {
func gifAnimatorIsReady(_ sender: JellyGifAnimator) {
sender.startAnimation()
}
func imageViewForAnimator(_ sender: JellyGifAnimator) -> UIImageView? {
for indexPath in collectionView.indexPathsForVisibleItems {
if animators[indexPath] === sender {
return (collectionView.cellForItem(at: indexPath) as? YourCustomCell)?.imageView
}
}
return nil
}
}
基准测试
显示 1 张图片
CPU 使用率 | 内存使用率 | |
---|---|---|
SwiftyGif | 2% | 44.6Mb |
Gifu | 2% | 46.3Mb |
JellyGif | 1% | 46.3Mb |
JellyGif(优化模式开启) | 1% | 30.3Mb |
显示 10 张图片
CPU 使用率 | 内存使用率 | |
---|---|---|
SwiftyGif | 34% | 31.7Mb |
Gifu | 6% | 200Mb |
JellyGif | 6% | 200Mb |
JellyGif(优化模式开启) | 5% | 39.1Mb |
在 iPhone Xs Max,iOS 13.3.1 和 Xcode 11.3.1 上进行测量
兼容性
- iOS 10.0+
- Swift 5.0
- Xcode 10+