{"id":2369,"date":"2021-04-17T21:45:08","date_gmt":"2021-04-17T13:45:08","guid":{"rendered":"http:\/\/123.57.164.21\/?p=2369"},"modified":"2021-04-17T21:45:08","modified_gmt":"2021-04-17T13:45:08","slug":"swiftui-%e4%b8%ad%e6%98%be%e7%a4%bagif%e5%9b%be%e7%89%87","status":"publish","type":"post","link":"https:\/\/92it.top\/?p=2369","title":{"rendered":"SwiftUI \u4e2d\u663e\u793agif\u56fe\u7247"},"content":{"rendered":"\n<p>\u6709\u65f6\u5019\u6211\u4eec\u9700\u8981\u5728View\u4e2d\u663e\u793aGif\u56fe\u7247\uff0c\u9700\u8981\u501f\u52a9GifImageViewController<\/p>\n\n\n\n<ul><li>\u628a\u56fe\u7247\u62f7\u8d1d\u5230\u5de5\u7a0b<\/li><\/ul>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/123.57.164.21\/wp-content\/uploads\/2021\/04\/image-78.png\" alt=\"\" class=\"wp-image-2372\" width=\"479\" height=\"151\" srcset=\"https:\/\/92it.top\/wp-content\/uploads\/2021\/04\/image-78.png 526w, https:\/\/92it.top\/wp-content\/uploads\/2021\/04\/image-78-300x95.png 300w, https:\/\/92it.top\/wp-content\/uploads\/2021\/04\/image-78-230x73.png 230w, https:\/\/92it.top\/wp-content\/uploads\/2021\/04\/image-78-350x110.png 350w, https:\/\/92it.top\/wp-content\/uploads\/2021\/04\/image-78-480x151.png 480w\" sizes=\"(max-width: 479px) 100vw, 479px\" \/><\/figure><\/div>\n\n\n\n<ul><li>\u5728SwiftUI\u4e2d \u8c03\u7528GifImageView\u5373\u53ef\u3002<\/li><\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct LoadingView: View {\n    @State var gifName: String = \"Loading\"\n    var body: some View {\n        VStack(alignment: .center, spacing: 0){  \n            GifImageView(imageName: self.$gifName)<\/pre>\n\n\n\n<ul><li>GifImageView\u4ee3\u7801 \u6ce8\u610f\u4fee\u6539gifImageWithName \u56fe\u7247\u8def\u5f84\u3002<\/li><\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct GifImageView: UIViewControllerRepresentable{\n    @Binding var imageName: String\n\n    func makeUIViewController(context: Context) -> GifImageViewController {\n        let picker = GifImageViewController(imageName: self.imageName)\n\n        return picker\n    }\n    func updateUIViewController(_ uiViewController: GifImageViewController,context: UIViewControllerRepresentableContext&lt;GifImageView>) {\n        uiViewController.imageView.removeFromSuperview()\n        uiViewController.imageName = imageName\n        uiViewController.viewDidLoad()\n    }\n\n}\nclass GifImageViewController: UIViewController {\n\/\/    lazy var imageView: UIImageView = {\n    var imageView: UIImageView = UIImageView()\n\/\/            return imageView\n\/\/        }()\n    fileprivate var imageName: String = \"\"\n    convenience init(imageName: String) {\n        self.init()\n        self.imageName = imageName\n    }\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        \n        \/************************ Load GIF image Using Name ********************\/\n\/\/        print(self.imageName)\n        let jeremyGif = UIImage.gifImageWithName(self.imageName)\n        imageView = UIImageView(image: jeremyGif)\n\/\/        imageView.frame = self.view.bounds\n        imageView.frame = CGRect(x: 0, y: 0, width: 42, height: 42)\n        view.addSubview(imageView)\n        \n        \/************************ Load GIF image Using Data ********************\/\n        \n\/\/        let imageData = try? Data(contentsOf: Bundle.main.url(forResource: \"play\", withExtension: \"gif\")!)\n\/\/        let advTimeGif = UIImage.gifImageWithData(imageData!)\n\/\/        let imageView2 = UIImageView(image: advTimeGif)\n\/\/        imageView2.frame = CGRect(x: 20.0, y: 220.0, width: self.view.frame.size.width - 40, height: 150.0)\n\/\/        view.addSubview(imageView2)\n\/\/\n\/\/        \/************************ Load GIF image URL **************************\/\n\/\/\n\/\/        let gifURL : String = \"http:\/\/www.gifbin.com\/bin\/4802swswsw04.gif\"\n\/\/        let imageURL = UIImage.gifImageWithURL(gifURL)\n\/\/        let imageView3 = UIImageView(image: imageURL)\n\/\/        imageView3.frame = CGRect(x: 20.0, y: 390.0, width: self.view.frame.size.width - 40, height: 150.0)\n\/\/        view.addSubview(imageView3)\n\n    }\n\n    override func didReceiveMemoryWarning() {\n        super.didReceiveMemoryWarning()\n        \/\/ Dispose of any resources that can be recreated.\n    }\n\n\n}\n\nextension UIImage {\n    \n    public class func gifImageWithData(_ data: Data) -> UIImage? {\n        guard let source = CGImageSourceCreateWithData(data as CFData, nil) else {\n            print(\"image doesn't exist\")\n            return nil\n        }\n        \n        return UIImage.animatedImageWithSource(source)\n    }\n    \n    public class func gifImageWithURL(_ gifUrl:String) -> UIImage? {\n        guard let bundleURL:URL = URL(string: gifUrl)\n            else {\n                print(\"image named \\\"\\(gifUrl)\\\" doesn't exist\")\n                return nil\n        }\n        guard let imageData = try? Data(contentsOf: bundleURL) else {\n            print(\"image named \\\"\\(gifUrl)\\\" into NSData\")\n            return nil\n        }\n        \n        return gifImageWithData(imageData)\n    }\n    \n    \/\/ \u203bsubdirectory\u9700\u8981\u4fee\u6539\n    public class func gifImageWithName(_ name: String) -> UIImage? {\n        guard let bundleURL = Bundle.main\n            .url(forResource: name, withExtension: \"gif\", subdirectory: \"Music\") else {\n                print(\"SwiftGif: This image named \\\"\\(name)\\\" does not exist\")\n                return nil\n        }\n        guard let imageData = try? Data(contentsOf: bundleURL) else {\n            print(\"SwiftGif: Cannot turn image named \\\"\\(name)\\\" into NSData\")\n            return nil\n        }\n        \n        return gifImageWithData(imageData)\n    }\n    \n    class func delayForImageAtIndex(_ index: Int, source: CGImageSource!) -> Double {\n        var delay = 0.03\n        \n        let cfProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil)\n        let gifProperties: CFDictionary = unsafeBitCast(\n            CFDictionaryGetValue(cfProperties,\n                Unmanaged.passUnretained(kCGImagePropertyGIFDictionary).toOpaque()),\n            to: CFDictionary.self)\n        \n        var delayObject: AnyObject = unsafeBitCast(\n            CFDictionaryGetValue(gifProperties,\n                Unmanaged.passUnretained(kCGImagePropertyGIFUnclampedDelayTime).toOpaque()),\n            to: AnyObject.self)\n        if delayObject.doubleValue == 0 {\n            delayObject = unsafeBitCast(CFDictionaryGetValue(gifProperties,\n                Unmanaged.passUnretained(kCGImagePropertyGIFDelayTime).toOpaque()), to: AnyObject.self)\n        }\n        \n        delay = delayObject as! Double\n        \n        if delay &lt; 0.03 {\n            delay = 0.03\n        }\n        \n        return delay\n    }\n    \n    class func gcdForPair(_ a: Int?, _ b: Int?) -> Int {\n        var a = a\n        var b = b\n        if b == nil || a == nil {\n            if b != nil {\n                return b!\n            } else if a != nil {\n                return a!\n            } else {\n                return 0\n            }\n        }\n        \n        if a! &lt; b! {\n            let c = a\n            a = b\n            b = c\n        }\n        \n        var rest: Int\n        while true {\n            rest = a! % b!\n            \n            if rest == 0 {\n                return b!\n            } else {\n                a = b\n                b = rest\n            }\n        }\n    }\n    \n    class func gcdForArray(_ array: Array&lt;Int>) -> Int {\n        if array.isEmpty {\n            return 1\n        }\n        \n        var gcd = array[0]\n        \n        for val in array {\n            gcd = UIImage.gcdForPair(val, gcd)\n        }\n        \n        return gcd\n    }\n    \n    class func animatedImageWithSource(_ source: CGImageSource) -> UIImage? {\n        let count = CGImageSourceGetCount(source)\n        var images = [CGImage]()\n        var delays = [Int]()\n        \n        for i in 0..&lt;count {\n            if let image = CGImageSourceCreateImageAtIndex(source, i, nil) {\n                images.append(image)\n            }\n            \n            let delaySeconds = UIImage.delayForImageAtIndex(Int(i),\n                source: source)\n            delays.append(Int(delaySeconds * 1000.0)) \/\/ Seconds to ms\n        }\n        \n        let duration: Int = {\n            var sum = 0\n            \n            for val: Int in delays {\n                sum += val\n            }\n            \n            return sum\n        }()\n        \n        let gcd = gcdForArray(delays)\n        var frames = [UIImage]()\n        \n        var frame: UIImage\n        var frameCount: Int\n        for i in 0..&lt;count {\n            frame = UIImage(cgImage: images[Int(i)])\n            frameCount = Int(delays[Int(i)] \/ gcd)\n            \n            for _ in 0..&lt;frameCount {\n                frames.append(frame)\n            }\n        }\n        \n        let animation = UIImage.animatedImage(with: frames,\n            duration: Double(duration) \/ 1000.0)\n        \n        return animation\n    }\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u6709\u65f6\u5019\u6211\u4eec\u9700\u8981\u5728View\u4e2d\u663e\u793aGif\u56fe\u7247\uff0c\u9700\u8981\u501f\u52a9GifImageViewController \u628a\u56fe\u7247\u62f7\u8d1d\u5230\u5de5 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"_links":{"self":[{"href":"https:\/\/92it.top\/index.php?rest_route=\/wp\/v2\/posts\/2369"}],"collection":[{"href":"https:\/\/92it.top\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/92it.top\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/92it.top\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/92it.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2369"}],"version-history":[{"count":3,"href":"https:\/\/92it.top\/index.php?rest_route=\/wp\/v2\/posts\/2369\/revisions"}],"predecessor-version":[{"id":2373,"href":"https:\/\/92it.top\/index.php?rest_route=\/wp\/v2\/posts\/2369\/revisions\/2373"}],"wp:attachment":[{"href":"https:\/\/92it.top\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2369"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/92it.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2369"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/92it.top\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2369"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}