【Swift】WKWebViewでJavaScriptのコールバックを受けつける（WKUserContentControllerの使い方）

下記ブログの転載です！
https://rc-code.info/ios/post-194/

iOSにて、**`WKWebView`** でJavaScriptのコールバックを受けつける必要があったので備忘録。
今回は **`WKUserContentController`** を利用した方法を紹介します。
&nbsp;


## WKWebView の使い方

まずは **`WKWebView`** の基本的な使い方ですが、[こちら](https://developer.apple.com/documentation/webkit/wkwebview)を参考にしていただければと思います。
&nbsp;


## WKUserContentController の使い方
`WKUserContentController`は`JavaScript`からのコールバック受信や、スクリプトをWebビューに挿入する方法を提供します。
下記が導入のサンプルコードです。

```swift


import UIKit
import WebKit

class ViewController: UIViewController {
    
	var webView: WKWebView!
    
	override func loadView() {
        
		// ① WKUserContentController の生成
		let userContentController = WKUserContentController()
		// ② WKUserContentController にコールバックハンドラを登録
		userContentController.add(self, name: "jsCallbackHandler")
		
		let webConfiguration = WKWebViewConfiguration()
		// ③ WKWebViewConfiguration に生成した WKUserContentController を登録する
		webConfiguration.userContentController = userContentController
		
		webView = WKWebView(frame: .zero, configuration: webConfiguration)
		view = webView
	}
}

// ④ WKScriptMessageHandler　のデリゲートを記載
extension ViewController: WKScriptMessageHandler {
    
	// ⑤ JavaScript から呼び出されるコールバックハンドラ関数を記載
	func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
		switch message.name {
			case "jsCallbackHandler":
				print("Javascript message arrived: jsCallbackHandler")
			default:
				return
		}
	}
}
```

### 1 WKUserContentController の生成
`WKUserContentController`は`WKWebViewConfiguration`に格納する必要があるので、まずはインスタンスを生成します。
&nbsp;

### 2 WKUserContentController にコールバックハンドラを登録
`WKUserContentController`の**add関数**を用いて、`JavaScript`から実行したい関数を持つクラスインスタンス(`WKScriptMessageHandler`プロトコルに準拠したクラス)を第一引数に設定し、コールバックの判別に利用するための`String`を**name引数**に設定します。
この**add関数**は何度も実行できるので、複数のコールバックを処理したい場合は**name引数**を変更して実行すれば、後述するコールバック関数内で判定することができます。
&nbsp;

### 3 WKWebViewConfiguration に生成した WKUserContentController を登録する
生成した`WKUserContentController`インスタンスは、`WKWebViewConfiguration`の`userContentController`プロパティに格納します。
&nbsp;

### 4 WKScriptMessageHandler　のデリゲートを記載
上記`ViewController`はデリゲート先として`WKUserContentController`に渡され登録されているので、`WKScriptMessageHandler`プロトコルに準拠させる必要があります。
&nbsp;

### 5 JavaScript から呼び出されるコールバックハンドラ関数を記載
**`WKScriptMessageHandler`プロトコル**に準拠させるために、`userContentController関数`を実装します。この関数を実装する事で、`Javascript`からのコールバックを受け付けることができるようになります。

JSからは下記のように、②の箇所の**add関数**にて`name引数`に指定したコールバックを実行します。

```swift
	webkit.messageHandlers.jsCallbackHandler.postMessage("Message from Javascript");
```

コールバックハンドラ内では`message.name`プロパティでコールバック名を取得することができるので、サンプルコードのように**switch文**等で判定する事で、処理を分岐させる事ができます。
&nbsp;

## 検証Playground

[検証Playground Git](https://github.com/rickeycode/UINSamplePlaygrounds/tree/master/WKWebView/WKWebViewConfigration/WKUserContentController)
&nbsp;

## 検証環境
**Mac:** 10.13.6
**XCode:** 10.1
**Swift:** 4.2.1
&nbsp;

## 参考ドキュメント
[公式 WKWebView ドキュメント](https://developer.apple.com/documentation/webkit/wkwebview)
[公式 WKWebViewConfiguration ドキュメント](https://developer.apple.com/documentation/webkit/wkwebviewconfiguration)
[公式 WKUserContentController ドキュメント](https://developer.apple.com/documentation/webkit/wkusercontentcontroller)
&nbsp;
&nbsp;