ios - 让 invokeUndefinedMethodFromWebScript 在 Swift 中工作

标签 ios swift xcode macos wkwebview

我正在尝试让 Javascript-Swift 界面与 WKWebView 一起工作,似乎有人已经让它工作了 here .

但是我无法让它在 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 似乎以某种方式让它工作(见上面的链接)。

有什么想法吗?

最佳答案

你发现了一篇旧文章,它是为 macOS 的一个古老的 WebView 而写的,而不是为 WKWebView 写的。

当使用 WKWebView 时,您使用 WKScriptMessageHandler 在 JavaScript 和 Swift 之间进行交互。

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

    //...
}

关于ios - 让 invokeUndefinedMethodFromWebScript 在 Swift 中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54264550/

相关文章:

ios - 尽管项目编译并且可以搜索文件,但文件不在项目导航器中

ios - 无法从扩展中读取核心数据

iOS/Xcode : Coredata:property name private appears red in Xcode

ios - 使用相同的开发人员和团队配置文件从两台不同的 Mac 分发应用程序

ios 快速碰撞检测

ios - UIActivityIndi​​catorView 停止旋转

ios - 如何让CAKeyframeAnimation在动画期间与用户交互?

ios - 取出过滤后的数据,再次过滤Coredata中的数据

objective-c - API 应该为 int 参数返回 NULL 吗? + 如何处理

ios - Swift:数组在类之间不发生变化?