Получение invokeUndefinedMethodFromWebScript для работы в Swift - PullRequest
0 голосов
/ 19 января 2019

Я пытаюсь заставить работать интерфейс Javascript-Swift с WKWebView, и, кажется, кто-то заставил его работать здесь .

Однако я не могу заставить его работать в Swift (яновый для Swift и новый для Obj-C).Я попробовал следующий код в ViewController.swift с WKWebView, добавленным в Main.storyboard и подключенным:

import WebKit

class ViewController: NSViewController, WKUIDelegate {
    @IBOutlet weak var wkWebView: WKWebView!
    override func viewDidLoad() {
        super.viewDidLoad()
        let url = URL(string: "http://127.0.0.1:8080")
        let request = URLRequest(url: url!)
        wkWebView!.configuration.preferences.javaScriptEnabled = true
        wkWebView!.load(request)
    }
}

extension WKWebView {
    open override func invokeUndefinedMethod(fromWebScript name: String!, withArguments arguments: [Any]!) -> Any! {
        return "Hello From Swift"
    }
}

и на стороне HTML:

<html>
  <body>
    <p>Hello World</p>
    <input type=text id='i'/>
    <input type=button value='Submit' onclick='document.getElementById(\"i\").value = window.external.MY_ObjectiveCFunction();'>
  </body>
</html>

Но когда я нажимаю кнопку «Отправить», ничего не происходит,Если я использую document.getElementById("i") = "hello", это работает, хотя.@ctrlspace, похоже, как-то работает (см. ссылку выше).

Есть идеи?

1 Ответ

0 голосов
/ 19 января 2019

Вы нашли старую статью, написанную для древнего WebView macOS, а не для WKWebView.

Вы используете WKScriptMessageHandler для взаимодействия между JavaScript и Swift, когда используете WKWebView.

ViewController.swift:

import WebKit

class ViewController: NSViewController, WKUIDelegate {
    @IBOutlet weak var wkWebView: WKWebView!
    override func viewDidLoad() {
        super.viewDidLoad()
        let url = Bundle.main.url(forResource: "index", withExtension: "html")! //Simplified for testing
        let request = URLRequest(url: url)
        wkWebView.configuration.preferences.javaScriptEnabled = true
        wkWebView.configuration.userContentController.add(self, name: "mySwiftMessage") //<-
        wkWebView.load(request)
    }

    //...
}

extension ViewController: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        switch message.name {
        case "mySwiftMessage":
            if let callbackName = message.body as? String {
                message.webView?.evaluateJavaScript("\(callbackName)('Hello From Swift');", completionHandler: nil)
            }
        default:
            break
        }
    }
}

index.html:

<html>
    <body>
        <script>
            function myCallback(value) {
                document.getElementById("i").value = value;
            }
        </script>
        <p>Hello World</p>
        <input type=text id='i'/>
        <input type=button value='Submit' onclick='window.webkit.messageHandlers.mySwiftMessage.postMessage("myCallback");'>
    </body>
</html>

Сложение

Чтобы WKWebView работал на более ранних версиях iOS, чем 11, вам просто нужно создать его экземпляр программно:

import WebKit

class ViewController: UIViewController, WKUIDelegate {

    var wkWebView: WKWebView! //<- NOT an IBOutlet

    override func viewDidLoad() {
        super.viewDidLoad()
        let webConfig = WKWebViewConfiguration()
        webConfig.preferences.javaScriptEnabled = true
        webConfig.userContentController.add(self, name: "mySwiftMessage")
        wkWebView = WKWebView(frame: self.view.bounds, configuration: webConfig)
        view.addSubview(wkWebView)
        //You may need to add some constraints...
        //And create a better `index.html` for iOS...
        let url = Bundle.main.url(forResource: "index", withExtension: "html")!
        let request = URLRequest(url: url)
        wkWebView.load(request)
    }

    //...
}
...