Swift webview: как правильно называть быстрый код из javascript?

Я пытаюсь сделать мой javascript взаимодействием с быстрым кодом, но, к сожалению, мне это не удалось.

На данный момент я просто попытался изменить цвета заголовков и отобразить сообщение, которое вы увидите в коде ниже.

Вот мой (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>

Здесь мой (main.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.
    }


}

Ответ 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!
}

Ответ 2

мои 2 цента, используя обратный вызов javascript с JSON... для полного определения класса и макета, см. adam code

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