如何在Swift中加载GIF图像?

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

我有一个带有 GIF 横幅 URL 的字符串,我需要将其放入应用程序中。

我的代码:

func showAdd(){
    Request.get("http://www.kyst.no/api/?apiMode=advertisement&lang=no", { (error: NSError?, data: NSData, text: NSString?) -> () in
        let jsonResult: Dictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as Dictionary<String, AnyObject>
        var banner : NSString = jsonResult["advertisement"]!["banner"] as NSString
        self.addViewImage.image = UIImage.animatedImageNamed(banner, duration: 1)
    })
}

但是什么也没发生。请帮忙。

ios swift uiimageview uiviewanimation
10个回答
174
投票

快速加载 GIF 图像:

##参考。

#1:从此链接复制 swift 文件 :

#2:使用名称加载 GIF 图像

    let jeremyGif = UIImage.gifImageWithName("funny")
    let imageView = UIImageView(image: jeremyGif)
    imageView.frame = CGRect(x: 20.0, y: 50.0, width: self.view.frame.size.width - 40, height: 150.0)
    view.addSubview(imageView)

#3:使用数据加载GIF图像

    let imageData = try? Data(contentsOf: Bundle.main.url(forResource: "play", withExtension: "gif")!)
    let advTimeGif = UIImage.gifImageWithData(imageData!)
    let imageView2 = UIImageView(image: advTimeGif)
    imageView2.frame = CGRect(x: 20.0, y: 220.0, width: 
    self.view.frame.size.width - 40, height: 150.0)
    view.addSubview(imageView2)

#4:使用 URL 加载 GIF 图像

    let gifURL : String = "http://www.gifbin.com/bin/4802swswsw04.gif"
    let imageURL = UIImage.gifImageWithURL(gifURL)
    let imageView3 = UIImageView(image: imageURL)
    imageView3.frame = CGRect(x: 20.0, y: 390.0, width: self.view.frame.size.width - 40, height: 150.0)
    view.addSubview(imageView3)

下载演示代码

输出:

iPhone 8 / iOS 11 / xCode 9


43
投票

本地 gif 的简单扩展。获取gif中的所有图像并将其添加到imageViewanimationImages中。

extension UIImageView {
    static func fromGif(frame: CGRect, resourceName: String) -> UIImageView? {
        guard let path = Bundle.main.path(forResource: resourceName, ofType: "gif") else {
            print("Gif does not exist at that path")
            return nil
        }
        let url = URL(fileURLWithPath: path)
        guard let gifData = try? Data(contentsOf: url),
            let source =  CGImageSourceCreateWithData(gifData as CFData, nil) else { return nil }
        var images = [UIImage]()
        let imageCount = CGImageSourceGetCount(source)
        for i in 0 ..< imageCount {
            if let image = CGImageSourceCreateImageAtIndex(source, i, nil) {
                images.append(UIImage(cgImage: image))
            }
        }
        let gifImageView = UIImageView(frame: frame)
        gifImageView.animationImages = images
        return gifImageView
    }
}

使用方法:

 guard let confettiImageView = UIImageView.fromGif(frame: view.frame, resourceName: "confetti") else { return }
 view.addSubview(confettiImageView)
 confettiImageView.startAnimating()

使用 UIImageView API 进行重复和持续时间自定义。

confettiImageView.animationDuration = 3
confettiImageView.animationRepeatCount = 1

当您完成 gif 动画并想要释放内存时。

confettiImageView.animationImages = nil

18
投票

首先安装一个 Pod :-

pod 'SwiftGifOrigin'

并导入到你的班级中

import SwiftGifOrigin

然后在viewDidiload方法中写入这段代码

yourImageView.image = UIImage.gif(name: "imageName")

注意:- 请不要在 gif 文件名中包含文件扩展名。例如:-

//Don't Do this
yourImageView.image = UIImage.gif(name: "imageName.gif")

查看来源:https://github.com/swiftgif/SwiftGif


11
投票

您可以尝试这个新库。 JellyGif 尊重 Gif 帧持续时间,同时具有较高的 CPU 和内存性能。它也适用于 UITableViewCell 和 UICollectionViewCell。要开始,您只需要

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))

有关更多信息,您可以查看其 README


11
投票
import UIKit
import ImageIO

extension UIImage {

public class func gifImageWithData(data: NSData) -> UIImage? {
    guard let source = CGImageSourceCreateWithData(data, nil) else {
        print("image doesn't exist")
        return nil
    }
    
    return UIImage.animatedImageWithSource(source: source)
}

public class func gifImageWithURL(gifUrl:String) -> UIImage? {
    guard let bundleURL = NSURL(string: gifUrl)
        else {
            print("image named \"\(gifUrl)\" doesn't exist")
            return nil
    }
    guard let imageData = NSData(contentsOf: bundleURL as URL) else {
        print("image named \"\(gifUrl)\" into NSData")
        return nil
    }
    
    return gifImageWithData(data: imageData)
}

public class func gifImageWithName(name: String) -> UIImage? {
    guard let bundleURL = Bundle.main
        .url(forResource: name, withExtension: "gif") else {
            print("SwiftGif: This image named \"\(name)\" does not exist")
            return nil
    }
    
    guard let imageData = NSData(contentsOf: bundleURL) else {
        print("SwiftGif: Cannot turn image named \"\(name)\" into NSData")
        return nil
    }
    
    return gifImageWithData(data: imageData)
}

class func delayForImageAtIndex(index: Int, source: CGImageSource!) -> Double {
    var delay = 0.1
    
    let cfProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil)
    let gifProperties: CFDictionary = unsafeBitCast(CFDictionaryGetValue(cfProperties, Unmanaged.passUnretained(kCGImagePropertyGIFDictionary).toOpaque()), to: CFDictionary.self)
    
    var delayObject: AnyObject = unsafeBitCast(CFDictionaryGetValue(gifProperties, Unmanaged.passUnretained(kCGImagePropertyGIFUnclampedDelayTime).toOpaque()), to: AnyObject.self)
    
    if delayObject.doubleValue == 0 {
        delayObject = unsafeBitCast(CFDictionaryGetValue(gifProperties, Unmanaged.passUnretained(kCGImagePropertyGIFDelayTime).toOpaque()), to: AnyObject.self)
    }
    
    delay = delayObject as! Double
    
    if delay < 0.1 {
        delay = 0.1
    }
    
    return delay
}

class func gcdForPair(a: Int?, _ b: Int?) -> Int {
    var a = a
    var b = b
    if b == nil || a == nil {
        if b != nil {
            return b!
        } else if a != nil {
            return a!
        } else {
            return 0
        }
    }
    
    if a! < b! {
        let c = a!
        a = b!
        b = c
    }
    
    var rest: Int
    while true {
        rest = a! % b!
        
        if rest == 0 {
            return b!
        } else {
            a = b!
            b = rest
        }
    }
}

class func gcdForArray(array: Array<Int>) -> Int {
    if array.isEmpty {
        return 1
    }
    
    var gcd = array[0]
    
    for val in array {
        gcd = UIImage.gcdForPair(a: val, gcd)
    }
    
    return gcd
}

class func animatedImageWithSource(source: CGImageSource) -> UIImage? {
    let count = CGImageSourceGetCount(source)
    var images = [CGImage]()
    var delays = [Int]()
    
    for i in 0..<count {
        if let image = CGImageSourceCreateImageAtIndex(source, i, nil) {
            images.append(image)
        }
        
        let delaySeconds = UIImage.delayForImageAtIndex(index: Int(i), source: source)
        delays.append(Int(delaySeconds * 1000.0)) // Seconds to ms
    }
    
    let duration: Int = {
        var sum = 0
        
        for val: Int in delays {
            sum += val
        }
        
        return sum
    }()
    
    let gcd = gcdForArray(array: delays)
    var frames = [UIImage]()
    
    var frame: UIImage
    var frameCount: Int
    for i in 0..<count {
        frame = UIImage(cgImage: images[Int(i)])
        frameCount = Int(delays[Int(i)] / gcd)
        
        for _ in 0..<frameCount {
            frames.append(frame)
        }
    }
    
    let animation = UIImage.animatedImage(with: frames, duration: Double(duration) / 1000.0)
    
    return animation
}
}

这是针对 Swift 3 更新的文件


9
投票

如果有人告诉将 gif 放入任何文件夹而不是 asset 文件夹中,那就太好了


1
投票

SWIFT 5 中,您可以加载任何 .gif 图像,而无需使用任何第三方。 您只需添加此代码

extension UIImage {
    class func gifImageWithData(_ data: Data) -> UIImage? {
        guard let source = CGImageSourceCreateWithData(data as CFData, nil) else {
            return nil
        }
        
        let frameCount = CGImageSourceGetCount(source)
        var images: [UIImage] = []
        
        for i in 0..<frameCount {
            if let cgImage = CGImageSourceCreateImageAtIndex(source, i, nil) {
                let image = UIImage(cgImage: cgImage)
                images.append(image)
            }
        }
        
        return UIImage.animatedImage(with: images, duration: 0.0)
    }
}



import UIKit

// Assuming you have a UIImageView outlet named `gifImageView` in your view controller

guard let gifPath = Bundle.main.path(forResource: "example", ofType: "gif") else {
    print("Failed to find the GIF image.")
    return
}

guard let gifData = try? Data(contentsOf: URL(fileURLWithPath: gifPath)) else {
    print("Failed to load the GIF image data.")
    return
}

guard let gifImage = UIImage.gifImageWithData(gifData) else {
    print("Failed to create the GIF image.")
    return
}

// Set the loaded GIF image to the UIImageView
gifImageView.image = gifImage

在上面的示例中,将“example”替换为 GIF 文件的名称(不带文件扩展名),并确保 GIF 文件已添加到您的 Xcode 项目并包含在目标中。

请注意,该代码依赖于辅助方法 gifImageWithData(_:) 从 GIF 数据创建 UIImage。这是提供该方法的扩展:


0
投票

这对我有用

Podfile:

platform :ios, '9.0'
use_frameworks!

target '<Your Target Name>' do
pod 'SwiftGifOrigin', '~> 1.7.0'
end

用途:

// An animated UIImage
let jeremyGif = UIImage.gif(name: "jeremy")

// A UIImageView with async loading
let imageView = UIImageView()
imageView.loadGif(name: "jeremy")

// A UIImageView with async loading from asset catalog(from iOS9)
let imageView = UIImageView()
imageView.loadGif(asset: "jeremy")

有关更多信息,请点击此链接:https://github.com/swiftgif/SwiftGif


0
投票

如果您使用Kingfisher,您可以使用

AnimatedImageView

因此,在现有 imageView 的

Identity Inspector
(右侧菜单)中的 .xib 中,将类更改为
AnimatedImageView
Module
自动切换为
Kingfisher
。将 viewClass 中的
IBOutlet
的 Class 也更改为
AnimatedImageView


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)
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.