WKWebView WKScriptMessageHandler未使用iOS 10,XCode 8 beta调用

时间:2016-09-08 10:06:48

标签: wkwebview swift3 xcode8

我需要将我的代码更新为swift 3.下面的代码是完美的原始解决方案,但在XCode 8 beta和iOS 10中使用swift 3的用户内容控制器'当我使用原始的html + js代码调用本机端时,委托不会调用。

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

    }

5 个答案:

答案 0 :(得分:4)

我调试了很多时间和条件,我发现:

  
      
  1. JS中的函数postMessage()必须有参数参数永远不会为空

  2.   
  3. 参数必须为JSON类型

  4.   
  5. 例如:   webkit.messageHandlers.refreshWebPage.postMessage("status":"ok");

  6.   

如果您已遵循上述三个建议并且委托设置正确。将调用委托函数didReceiveScriptMessage。希望这能帮助你。

答案 1 :(得分:2)

我通过只有一个像

这样的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 :(得分:1)

您是否找到了修复方法?因为我也有问题但幸运的是,我可以发送消息并且userContentController确实回调了但是只有消息必须只有数字,没有字符串,没有字符。我不知道为什么......

<强>被修改 我找到了答案。 似乎你必须尝试捕获,在我这样做之后,它100%使用文本号甚至是json

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

并且不要忘记callbackHandler必须与iOS中的同一个单词才能使其正常工作,您不必为callbackHandler命名,您可以将其命名为任何内容,但必须在Javascript和iOS中都是一样的

希望它可以帮到你

答案 3 :(得分:1)

发生这种情况是因为基本上window.webkit.messageHandlersUserMessageHandlersNamespace类型。

您应该尝试传递字典而不是字符串或数组:

JavaScript部分:

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

Swift部分:

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)

答案 4 :(得分:0)

如果不是从JS使用webkit.messageHandlers.refreshWebPage

webkit.messageHandlers.refreshWebPage.postMessage("status":"ok")

然后您可以将其包装在WKUserContentController上,如下所示,这样您就可以回叫

let userController = WKUserContentController()

    let channelName = "postMessage"
    let wrapperSource = "window.\(channelName) = webkit.messageHandlers.\(channelName);"
    let wrapperScript = WKUserScript(
        source: wrapperSource,
        injectionTime: .atDocumentStart,
        forMainFrameOnly: false)
    userController.addUserScript(wrapperScript)
    userController.add(self, name: "postMessage")
    let configuration = WKWebViewConfiguration()
    configuration.userContentController = userController
    self.wkWebView = WKWebView(
               frame: self.view.bounds,
               configuration: configuration
           )