如何使用 UIKit 在没有任何第三方库的情况下在 iOS 应用程序中使用 GIF?

问题描述 投票:0回答:5

我目前正在开发一个严重依赖 GIF 的项目。然而,在我迷失之前,我从未在 Swift for iOS 中使用过 GIF。

我尝试的第一件事是将一些 GIF 导入到我的

Assets.xcassets
文件夹中。我意识到使用 ImageSet 来处理 GIF 是行不通的。

所以我的第一个问题: 如何将 GIF 导入到我的项目中?我应该只使用一种分辨率还是像图像那样使用三种更好的方式?

然后我已经检查了一些关于 在 a

UIImageView
中以编程方式和通过 Storyboard 呈现 GIF 的问题。正如我所发现的,这可能是通过使用
UIImage
类的扩展来实现的最好方法。但是,由于某种原因,Swift 4 示例对我不起作用。

所以我的第二个问题: 如何在项目中使用导入的 GIF 并以编程方式在

UIImageView
中显示它们?

ios swift uiimageview gif
5个回答
2
投票

如果您的 gif 动画的所有帧都有恒定的帧时间,那么您可以轻松地从资产目录中加载它,而无需第三方库:

extension UIImage {
    static func animatedGif(named: String, framesPerSecond: Double = 10) -> UIImage? {
        guard let asset = NSDataAsset(name: named) else { return nil }
        return animatedGif(from: asset.data, framesPerSecond: framesPerSecond)
    }

    static func animatedGif(from data: Data, framesPerSecond: Double = 10) -> UIImage? {
        guard let source = CGImageSourceCreateWithData(data as CFData, nil) else { return nil }
        let imageCount = CGImageSourceGetCount(source)
        var images: [UIImage] = []
        for i in 0 ..< imageCount {
            if let cgImage = CGImageSourceCreateImageAtIndex(source, i, nil) {
                images.append(UIImage(cgImage: cgImage))
            }
        }
        return UIImage.animatedImage(with: images, duration: Double(images.count) / framesPerSecond)
    }
}

1
投票

您必须手动解码 GIF 数据,然后才能逐帧显示它。您在这里不会有任何简单的答案,因为这绝对是非常困难的想法,请尝试从第三方和播放器复制解码算法或只是使用它。像 SDWebImage 这样的东西将是您的最佳选择。检查 SDAnimatedImagePlayer、SDWebAnimatedImage 类。


0
投票

我也有这样的问题需要解决。我发现这个线程中的答案很有帮助。请检查一下。 在Iphone UIImageView中添加动画Gif图像

此外,我强烈建议您查看 FLAnimatedImage 中的一些实现。它处理 iOS 中 GIF 可能需要的显示、播放和其他功能。


0
投票

iOS 13 之后使用

CGAnimateImageDataWithBlock
CGAnimateImageAtURLWithBlock

extension UIImageView: SupportProduct {
    
    public func load(name: String, in bundle: Bundle = .main) {
        if let data = NSDataAsset(name: name, bundle: bundle)?.data {
            CGAnimateImageDataWithBlock(data as CFData, nil) { (_, cgImage, _) in
                self.image = UIImage(cgImage: cgImage)
            }
        }
    }
}

0
投票

除了yycking的答案(由于声誉我无法发表评论),你必须手动停止'CGAnimateImageDataWithBlock'。如果没有,即使 UIImageView 为零,它仍然会动画。

所以最终的代码是:

extension UIImageView {
    func loadGIF(name: String, in bundle: Bundle = .main) {
        if let data = NSDataAsset(name: name, bundle: bundle)?.data {
            CGAnimateImageDataWithBlock(data as CFData, nil) { [weak self] (index, cgImage, stop) in
                // NOTE: without 'stop.pointee = true', even if self is nil, animating will not be stopped
                guard let self = self else {
                    stop.pointee = true
                    return
                }
                self.image = UIImage(cgImage: cgImage)
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.