Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WKWebView WKScriptMessageHandler not called with iOS 10, Xcode 8 beta

I need to update my code to swift 3. The code below is the original solution what is works perfectly, but in Xcode 8 beta and iOS 10 with swift 3 the userContentController delegate does not called when I use the original html+js code to call the native side.

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)")

    }
like image 201
NYS Avatar asked Sep 08 '16 10:09

NYS


2 Answers

Afer I debug a lot of times and conditions , I found that :

  1. The function postMessage() in your JS must have a parameter, the parameter never be null

  2. The parameter must be JSON type

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

If you have followed the three advices above and have the delegate set correct. The delegate function didReceiveScriptMessage will be called. Hope this help you.

like image 118
guozqzzu Avatar answered Nov 15 '22 16:11

guozqzzu


Do you find the way to fix it? because I have a problem also but Fortunately, I could send the message and userContentController did called back but only message has to be in number only, no string, no characters. I don't know why...

Edited I have found out the answer about this. It's seem that you have to put in try catch and after I did that it's 100% working with text number or even json

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

And Don't forget that callbackHandler has to be the same word in the iOS to make it work, you don't have to name callbackHandler, you could name it anything but it has to be the same in both Javascript and iOS

Hope it helps you

like image 4
Einzeln Avatar answered Nov 15 '22 15:11

Einzeln