有时候我们需要在View中显示Gif图片,需要借助GifImageViewController
- 把图片拷贝到工程

- 在SwiftUI中 调用GifImageView即可。
struct LoadingView: View { @State var gifName: String = "Loading" var body: some View { VStack(alignment: .center, spacing: 0){ GifImageView(imageName: self.$gifName)
- GifImageView代码 注意修改gifImageWithName 图片路径。
struct GifImageView: UIViewControllerRepresentable{ @Binding var imageName: String func makeUIViewController(context: Context) -> GifImageViewController { let picker = GifImageViewController(imageName: self.imageName) return picker } func updateUIViewController(_ uiViewController: GifImageViewController,context: UIViewControllerRepresentableContext<GifImageView>) { uiViewController.imageView.removeFromSuperview() uiViewController.imageName = imageName uiViewController.viewDidLoad() } } class GifImageViewController: UIViewController { // lazy var imageView: UIImageView = { var imageView: UIImageView = UIImageView() // return imageView // }() fileprivate var imageName: String = "" convenience init(imageName: String) { self.init() self.imageName = imageName } override func viewDidLoad() { super.viewDidLoad() /************************ Load GIF image Using Name ********************/ // print(self.imageName) let jeremyGif = UIImage.gifImageWithName(self.imageName) imageView = UIImageView(image: jeremyGif) // imageView.frame = self.view.bounds imageView.frame = CGRect(x: 0, y: 0, width: 42, height: 42) view.addSubview(imageView) /************************ Load GIF image Using Data ********************/ // 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) // // /************************ Load GIF image URL **************************/ // // 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) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } } extension UIImage { public class func gifImageWithData(_ data: Data) -> UIImage? { guard let source = CGImageSourceCreateWithData(data as CFData, nil) else { print("image doesn't exist") return nil } return UIImage.animatedImageWithSource(source) } public class func gifImageWithURL(_ gifUrl:String) -> UIImage? { guard let bundleURL:URL = URL(string: gifUrl) else { print("image named \"\(gifUrl)\" doesn't exist") return nil } guard let imageData = try? Data(contentsOf: bundleURL) else { print("image named \"\(gifUrl)\" into NSData") return nil } return gifImageWithData(imageData) } // ※subdirectory需要修改 public class func gifImageWithName(_ name: String) -> UIImage? { guard let bundleURL = Bundle.main .url(forResource: name, withExtension: "gif", subdirectory: "Music") else { print("SwiftGif: This image named \"\(name)\" does not exist") return nil } guard let imageData = try? Data(contentsOf: bundleURL) else { print("SwiftGif: Cannot turn image named \"\(name)\" into NSData") return nil } return gifImageWithData(imageData) } class func delayForImageAtIndex(_ index: Int, source: CGImageSource!) -> Double { var delay = 0.03 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.03 { delay = 0.03 } 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(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(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(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 } }