【问题标题】:Getting invokeUndefinedMethodFromWebScript to work in Swift让 invokeUndefinedMethodFromWebScript 在 Swift 中工作
【发布时间】:2019-01-19 06:10:27
【问题描述】:

我正在尝试让 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 似乎已经让它以某种方式工作了(见上面的链接)。

有什么想法吗?

【问题讨论】:

    标签: ios swift xcode macos wkwebview


    【解决方案1】:

    您发现了一篇旧文章,它是为 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)
        }
    
        //...
    }
    

    【讨论】:

    • 感谢您提供完整有效的解决方案。我还想让 UIWebView 支持 iOS 9.0+,因为 WKWebView 仅适用于 iOS11+。有可能吗?
    • 我找不到这样优雅的 UIWebView 解决方案。似乎只有解决方法可用(例如加载自定义网址)
    • 您误认为WKWebView 的可用性自iOS 8 起可用。只是在iOS 11 之前您不能将情节提要用于WKWebView。您只需要以编程方式实例化WKWebView
    • 太棒了.. 那也有效.. 我希望我能多次投票给你.. 非常感谢!!
    猜你喜欢
    • 2016-04-04
    • 2015-10-08
    • 2015-02-26
    • 2018-07-25
    • 2015-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多