Swiftで取得した画像をWKWebView内のHTMLで表示する方法

WkWebviewのコンテンツ内でSwiftで取得したPNG画像などのデータを使いたいケースがあると思います。

本記事では[WebViewJavascriptBridge](https://github.com/marcuswestin/WebViewJavascriptBridge)を使用した、PNG画像のSwiftとJavaScript間での通信にて表示する方法について記載します。

## ローカルのHTMLをWebViewで読み込み(Swift)

まずはWKWebviewでローカルのhtmlを読み込む。

```Swift:Swift
class ViewController: UIViewController {
    var webView:WKWebView?

    override func viewDidLoad() {
        super.viewDidLoad()
        // WKWebViewのViewへの追加
        self.webView = WKWebView(frame: view.frame)
        view.addSubview(self.webView!)
        let htmlPath = Bundle.main.path(forResource: "content", ofType: "html")
        let baseURL = URL.init(fileURLWithPath: htmlPath!)
        webView!.loadFileURL(baseURL, allowingReadAccessTo: baseURL)
    }
}
```

## JavaScriptへのbridge(Swift)

WebViewJavascriptBridgeの初期化と、
registerHandlerにてJavaScript→Swiftへアクセスする受け口作成。

```Swift:Swift
        self.bridge = WebViewJavascriptBridge.init(forWebView: webView)
        // WKWebView内のjavascriptからSwift内のデータを取得
        self.bridge!.registerHandler("image") { (data, callback) in
        }
```

## JavaScript側のbridge設定(JavaScript)

読み込むhtml内のJavaScriptにてWebViewJavascriptBridgeでSwift間通信するためのテンプレートを追加後、
bridge.callHandlerにてSwift側への画像取得要求を行う。
※詳細は[WebViewJavascriptBridge](https://github.com/marcuswestin/WebViewJavascriptBridge)参照

```js:JavaScript
        function setupWebViewJavascriptBridge(callback) {
            if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
            if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
            window.WVJBCallbacks = [callback];
            var WVJBIframe = document.createElement('iframe');
            WVJBIframe.style.display = 'none';
            WVJBIframe.src = 'https://__bridge_loaded__';
            document.documentElement.appendChild(WVJBIframe);
            setTimeout(function () { document.documentElement.removeChild(WVJBIframe) }, 0)
        }

        setupWebViewJavascriptBridge(function (bridge) {
            bridge.callHandler('image', { 'key': 'value' }, function responseCallback(responseData) {
            })
        })
```
## Base64データへの変換(Swift)

WKWebview側でPNGを読み込むためbase64のstringへ変換してJavaScript側へ返却。

```Swift:Swift
        self.bridge!.registerHandler("image") { (data, callback) in
            if let imagePath = Bundle.main.path(forResource: "PNG", ofType: "png") {
                // PNGをUIImageに
                let image = UIImage(contentsOfFile: imagePath)
                // Data型へ変換
                let data = image?.pngData()
                // PNGのデータをbase64エンコードしてWebViewで表示できるよう修正
                let base64Image = data?.base64EncodedString(options: .endLineWithLineFeed)
                callback!(base64Image)
            }
        }

```

## base64形式のPNGデータの読み込み

Swift側から返却されたbase64形式のresponseDataは、
PNGのデータURIとなっていないため、先頭に
data:image/png;base64,
を追加してimgタグで読み込み。

```js:JavaScript
            bridge.callHandler('image', { 'key': 'value' }, function responseCallback(responseData) {
                var html = [
                ];
                html += '<img src="data:image/png;base64,'
                html += responseData
                html += '" alt="PNG"/>'
                document.getElementById("content").innerHTML = html
            })
```

上記にてWKWebview上でSwiftで取得したPNGが表示される。

## サンプルアプリ

[GitHubにて上記ソースのサンプルアプリ公開しています。](https://github.com/ppp16g/WKWebViewImageTestApp)