Swift4 WKWebViewでローカルやWeb上のgifを再生するカスタムクラス

# はじめに
こんにちは:leaves:
gifを簡易的に再生したくなりましたが、ライブラリなどを使わずに、WebViewで表示するにはどうするのか気になったので調べてみました。今回はカスタムクラスとして書いてみました。
至らぬ点など多々あると思いますが、コメントなど頂けたら幸いです。

**ローカルのgif**
![hari.gif](https://qiita-image-store.s3.amazonaws.com/0/128250/76b16142-0542-63a1-d1ae-c911cca4177a.gif)<img src="https://qiita-image-store.s3.amazonaws.com/0/128250/5a833fa2-3b92-5184-a250-cd3c1020fa23.png" width="300">

**Web上のgif**
![sea.gif](https://qiita-image-store.s3.amazonaws.com/0/128250/a936eab9-42ca-26ad-d095-b2677f991566.gif)

# 実装について
WKWebViewでの実装では、gifを1度のみ再生したり、途中で止めたりなど細かくは指定できないのかなと思っています...。細かく設定するには、ライブラリの導入を考えてもいいかもしれません。

# ソースコード
カスタムクラスとして実装してみました。クラス名などご自由に変更してください。

```GifAnimateView.swift
import UIKit
import WebKit

class GifAnimateView: WKWebView {
    
    private var data: Data?
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        self.initialize()
    }
    
    private override init(frame: CGRect, configuration: WKWebViewConfiguration) {
        super.init(frame: frame, configuration: configuration)
        self.initialize()
    }
    
    convenience init?(fileName: String, origin: CGPoint = CGPoint.zero) {
        guard let url = Bundle.main.url(forResource: fileName, withExtension: "gif") else { return nil }
        guard let gifData = NSData(contentsOf: url) else { return nil }
        guard let image = UIImage(data: gifData as Data) else { return nil }
        self.init(frame: CGRect(origin: origin, size: image.size))
        self.data = gifData as Data
    }
    
    private func initialize() {
        self.scrollView.isScrollEnabled = false
        self.scrollView.isUserInteractionEnabled = false
    }
    /**
     gifを再生します (infinity animation)
     */
    func startAnimate() {
        guard let data = self.data else { return }
        self.load(data, mimeType: "image/gif", characterEncodingName: "utf-8", baseURL: NSURL() as URL)
    }
    /**
     gif再生を停止し、表示をクリーンします
     */
    func clear() {
        guard let url = URL(string: "about:blank") else { return }
        self.load(URLRequest(url: url))
    }
    /**
     URLからgifをロードします
     */
    static func setGifBy(url: String, origin: CGPoint = CGPoint.zero, completion: @escaping ((GifAnimateView) -> ())) {
        guard let url = URL(string: url) else { return }
        let task = URLSession.shared.dataTask(with: url) { data, response, error in
            if error == nil, case .some(let result) = data {
                guard let image = UIImage(data: result as Data) else { return }
                DispatchQueue.main.async {
                    let gifAnimateView = GifAnimateView(frame: CGRect(origin: origin, size: image.size))
                    gifAnimateView.data = result
                    completion(gifAnimateView)
                }
            }
        }
        task.resume()
    }
}
```

# 使い方
**ローカルのgif**
ファイル名を指定してカスタムViewを生成します。

<img src="https://qiita-image-store.s3.amazonaws.com/0/128250/a2d1b0e2-90cc-36f8-a0b7-62bf119a475f.gif" width="200">

```MainViewController.swift
import UIKit
import WebKit

class MainViewController: UIViewController {
    
    var gifView: GifAnimateView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.gifView = GifAnimateView(fileName: "hari")
        self.view.addSubview(gifView)
        self.gifView.center = self.view.center
    }
    
    @IBAction func startAction(_ sender: Any) {
        self.gifView?.startAnimate()
    }
    
    @IBAction func clearAction(_ sender: Any) {
        self.gifView?.clear()
    }
}
```

**Web上のgif**
URLを指定して`setByGif`すると、読み込み完了時にインスタンスが返ります。

<img src="https://qiita-image-store.s3.amazonaws.com/0/128250/a2d16c02-6dea-db83-4055-16193787eacc.gif" width="200">

```MainViewController.swift
import UIKit
import WebKit

class MainViewController: UIViewController {
    
    var gifView: GifAnimateView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let sea = "https://qiita-image-store.s3.amazonaws.com/0/128250/76b16142-0542-63a1-d1ae-c911cca4177a.gif"
        GifAnimateView.setGifBy(url: sea) { gifView in
            self.view.addSubview(gifView)
            self.gifView = gifView
            self.gifView.center = self.view.center
        }
    }
    
    @IBAction func startAction(_ sender: Any) {
        self.gifView?.startAnimate()
    }
    
    @IBAction func clearAction(_ sender: Any) {
        self.gifView?.clear()
    }
}
```

# 参考にさせていただいた記事
- [Swift 3: Load GIF in UIWebView
 Stackoverflow](https://stackoverflow.com/questions/40747912/swift-3-load-gif-in-uiwebview)