【问题标题】:Swift webview: How to call correctly swift code from javascript?Swift webview:如何从 javascript 中正确调用 swift 代码?
【发布时间】:2014-09-13 20:27:06
【问题描述】:

我正在尝试让我的 javascript 与 swift 代码交互,但不幸的是我没有成功。

目前,我只是尝试更改标题颜色并显示一条消息,如下面的代码所示。

这是我的 (index.html) 代码:

<!DOCTYPE html>
<html>
    <head>
        <title>Test</title>
        <meta charset="UTF-8">
    </head>
    <body>
        <h1>WebView Test</h1>
        <script type="text/javascript" src="main.js"></script>
    </body>
</html>

这是我的 (ma​​in.js -JavaScript) 代码:

function callNativeApp () {
    try {
        webkit.messageHandlers.callbackHandler.postMessage("Send from JavaScript");
    } catch(err) {
        console.log('error');
    }
}

setTimeout(function () {
    callNativeApp();
}, 5000);

function redHeader() {
    document.querySelector('h1').style.color = "red";
}

这是我的 (ViewController.swift) 代码:

import UIKit
import WebKit

class ViewController: UIViewController, WKScriptMessageHandler {

    @IBOutlet var containerView : UIView! = nil

    var webView: WKWebView?

    override func loadView() {
        super.loadView()

        var contentController = WKUserContentController();
        var userScript = WKUserScript(
            source: "redHeader()",
            injectionTime: WKUserScriptInjectionTime.AtDocumentEnd,
            forMainFrameOnly: true
        )
        contentController.addUserScript(userScript)
        contentController.addScriptMessageHandler(
            self,
            name: "callbackHandler"
        )

        var config = WKWebViewConfiguration()
        config.userContentController = contentController

        self.webView = WKWebView()
        self.view = self.webView!
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        var url = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("index", ofType: "html")!)
        var req = NSURLRequest(URL: url)
        self.webView!.loadRequest(req)
    }

    func userContentController(userContentController: WKUserContentController!,didReceiveScriptMessage message: WKScriptMessage!) {
            if(message.name == "callbackHandler") {
            println("JavaScript is sending a message \(message.body)")
            } }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

【问题讨论】:

标签: javascript ios xcode swift


【解决方案1】:

您已正确设置所有内容,但您没有将您的 WKWebViewConfiguration 实例提供给 WKWebView。由于配置有Javascript/Swift桥接的细节,不能来来回回。

override func loadView() {
    // ...
    var config = WKWebViewConfiguration()
    config.userContentController = contentController

    self.webView = WKWebView(frame: self.view.frame, configuration: config)
    self.view = self.webView!
}

【讨论】:

  • 请注意在loadView() 方法中调用self.view.frame 会导致EXC_BAD_ACCESS 崩溃。
  • @Dev 如果是 casugin,我应该叫什么 self.view.frame EXC_BAD_ACCESS
  • @Dev 只有在您忘记事先调用 super.loadView() 时才会这样做
  • MacOS版本呢?
【解决方案2】:

我的 2 美分,使用带有 JSON 的 javascript 回调...对于完整的类定义和布局,请参阅 adam 的代码

import UIKit
import WebKit

class ViewController: UIViewController, WKScriptMessageHandler {
    var webView: WKWebView?
    ...

然后

override func loadView() {
    let theConfiguration = WKWebViewConfiguration()
    let contentController = theConfiguration.userContentController

    // alert fix, at start to allow a JS script to overwrite it
    contentController.addUserScript( WKUserScript(
        source: "window.alert = function(message){window.webkit.messageHandlers.messageBox.postMessage({message:message});};",
        injectionTime: WKUserScriptInjectionTime.AtDocumentStart,
        forMainFrameOnly: true
    ) )
    contentController.addScriptMessageHandler(self, name: "messageBox")

    self.webView = WKWebView(frame: self.view.frame, configuration: theConfiguration)

    // and here things like: self.webView!.navigationDelegate = self
    self.view = self.webView!  // fill controllers view
}

特别是

func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {

    if message.name == "messageBox" {
        let sentData = message.body as! Dictionary<String, String>

        let message:String? = sentData["message"]

        let alertController = UIAlertController(title: nil, message: message, preferredStyle: UIAlertControllerStyle.Alert)
        alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment:"btnOK"), style: .Default, handler: nil))
        self.presentViewController(alertController, animated: true) {}
    }
}

【讨论】:

  • 您好,您能帮我提供一下它的 MacOS 版本吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多