web-dev-qa-db-ja.com

WKWebView WKScriptMessageHandlerがiOS 10、Xcode 8ベータで呼び出されない

コードをSwift 3.に更新する必要があります。以下のコードは完全に機能する元のソリューションですが、Xcode 8ベータ版とiOS 10ではSwift 3元のhtml + jsコードを使用してネイティブ側を呼び出すときに、userContentControllerデリゲートが呼び出されません。

class ViewController: UIViewController, WKUIDelegate, WKScriptMessageHandler, WKNavigationDelegate,UIWebViewDelegate,CLLocationManagerDelegate,URLSessionDataDelegate,UIImagePickerControllerDelegate, UINavigationControllerDelegate {

....

func initWebView(){
    // JAVASCRIPT PART
    let contentController = WKUserContentController();

    let jScript:String = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";

    let wkUScript:WKUserScript = WKUserScript(source: jScript, injectionTime: WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: true);


    contentController.addUserScript(wkUScript)
    contentController.add(
        self,
        name: "refreshWebPage"
    )
    contentController.add(
        self,
        name: "forceStepBack"
    )
    contentController.add(
        self,
        name: "setPageTitle"
    )
    contentController.add(
        self,
        name: "allowBackNavigate"
    )
    contentController.add(
        self,
        name: "changeBackNavigationURL"
    )

    contentController.add(
        self,
        name: "changeLeftButtonIconVisibility"
    )
    contentController.add(
        self,
        name: "changeRightButtonIconVisibility"
    )
    contentController.add(
        self,
        name: "clearWebCache"
    )
    contentController.add(
        self,
        name: "changeMobileAndPassword"
    )


    let config = WKWebViewConfiguration()
    config.userContentController = contentController


    self.webView = WKWebView(frame: CGRect.zero, configuration: config)


    self.view.translatesAutoresizingMaskIntoConstraints = false
    self.webView!.navigationDelegate = self
    self.webView!.uiDelegate = self;
    self.webView!.scrollView.bounces = false;
    view = webView

    webView?.loadHTMLString(self.baseURL!, baseURL: nil)

}
...
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        print("JavaScript is sending a message: \(message.body)")
        print("JavaScript is sending a message.name: \(message.name)")

    }
10
NYS

私は多くの時間と条件をデバッグした後、それを見つけました:

  1. JSの関数postMessage()にはparameterが必要ですparameterはnullにできません

  2. パラメータJSONタイプでなければなりません

  3. 例:webkit.messageHandlers.refreshWebPage.postMessage("status":"ok");

上記の3つのアドバイスに従ってデリゲートを正しく設定した場合。デリゲート関数didReceiveScriptMessageが呼び出されます。これがお役に立てば幸いです。

5
guozqzzu

私はこれを次のような1つのcontentControllerだけを持つことで修正しました

let contentController = WKUserContentController()
contentController.add(self, name: "MyStuff")

次に、userContentController関数で本体を解析して、要求されたアクションとその他のパラメーターを判別します。 {action: "doThis"、params:[1,2,3]}を送信すると、解析コードは次のようになります。

if message.name == "MyStuff" {
    let cmd:NSDictionary = message.body as! NSDictionary
    let action:String = cmd["action"] as! String
    switch action {
    case "doThis":
        // Do my stuff
        break
    default:
        break
    }
}
2
Laurel Zenner

あなたはそれを修正する方法を見つけましたか?私にも問題がありますが、幸いにもメッセージを送信でき、userContentControllerがコールバックしましたが、メッセージのみが数字のみで、文字列も文字もない必要があります。理由はわかりません...

編集済みこれに関する答えを見つけました。あなたはトライキャッチを入れなければならないようです、そして私がそれをした後それはテキスト番号またはjsonでさえ100%働いています

`<script>
    function callNative(message)  {
    try {
        webkit.messageHandlers.callbackHandler.postMessage(message)
    } catch(err) {
        console.log("Error")
    }
    }
</script>`

callbackHandlerを機能させるには、iOSで同じWordにする必要があることを忘れないでください。callbackHandlerに名前を付ける必要はありません。任意の名前を付けることができますが、両方のJavaScriptで同じにする必要があります。およびiOS

それがあなたを助けることを願っています

2
Einzeln

基本的にwindow.webkit.messageHandlersUserMessageHandlersNamespaceタイプです。

文字列や配列の代わりに辞書を渡そうとする必要があります:

JavaScriptの部分:

var dictionary = {"key1":"value1", "key2":"value2", "subDictionary": {"name": "foo"}}
webkit.messageHandlers.refreshWebPage.postMessage(dictionary);

スイフト部分:

func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        let body = message.body
        if let dict = body as? Dictionary<String, AnyObject> {
            if let test = dict["key1"] {
                print("JavaScript is sending a message \(value1)")
            }
        }
}

P.S。(私のテストによれば、これはiOS9、iOS10の両方で機能します)

1