Swift webview:如何从 javascript 中正确调用 swift 代码?

Posted

技术标签:

【中文标题】Swift webview:如何从 javascript 中正确调用 swift 代码?【英文标题】:Swift webview: How to call correctly swift code from javascript? 【发布时间】: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.
    



【问题讨论】:

Apple 的 loadView 文档 developer.apple.com/documentation/uikit/uiviewcontroller/… 说:“您对此方法的自定义实现不应调用 super。”这在接受的答案中可能并不明显。 【参考方案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 版本吗?

以上是关于Swift webview:如何从 javascript 中正确调用 swift 代码?的主要内容,如果未能解决你的问题,请参考以下文章

Xcode 在 Swift 中调试 webview 的 javascript

Android实现WebView和Js交互

Swift - 从 WebView 获取 js 对象

带有发布请求的swift3 webview

从 webview 链接 Swift 启动 waze

如果它进入webview(swift),如何在webview中打开链接