WKWebView WKScriptMessageHandler is not called with iOS 10, Xcode 8 beta

I need to upgrade my code to fast 3. The code below is an original solution that works fine, but in Xcode 8 beta and iOS 10 with fast 3, the userContentController delegate is not called when I use the original html + js to call my own 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)") } 
+6
source share
4 answers

Afer I debug many times and conditions, I found that:

  • The postMessage() function in your JS should have a parameter , parameter will never be null

  • Parameter must be JSON type

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

If you followed the three tips above and asked the delegate correctly. The didReceiveScriptMessage delegate function is didReceiveScriptMessage . Hope this helps you.

+4
source

I fixed this by only having one contentController as

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

Then, in the userContentController function, I analyze the body to determine the requested action and other parameters. If I send {action: "doThis", params: [1,2,3]}, my parsing code will look like this:

 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
source

Did you find a way to fix this? because I have a problem, but, fortunately, I could send a message, and the userContentController called back, but only the message should be only in the number, no line, no characters. I do not know why...

Edited I found out the answer about this. It seems that you need to try a try, and after I have done this, it works 100% with a text number or even with json

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

And do not forget that callbackHandler must be the same word in iOS, to make it work, you do not need to call callbackHandler, you can call it anything, but it must be the same as in Javascript and iOS

Hope this helps you

+1
source

This is because basically window.webkit.messageHandlers is a type of UserMessageHandlersNamespace .

You should try passing a dictionary instead of a string or array:

JavaScript part:

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

Quick part:

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

PS (it works like on iOS9, iOS10 according to my tests)

0
source

All Articles