Javascript 从 UIWebView 调用 Swift

问题描述 投票:0回答:3

我正在尝试从 UIWebView 中的 javascript 函数调用 iOS 10 中的 Swift。我设置了一个非常基本的项目只是为了尝试使其正常工作,代码如下。

import UIKit

class ViewController: UIViewController, UIWebViewDelegate  {    
  @IBOutlet var webView: UIWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let url = Bundle.main.url(forResource: "products", withExtension: "html")
        let request = NSURLRequest(url: url! as URL)
        webView.loadRequest(request as URLRequest)
    }

    @IBAction func closeDocumentViewer() {
        displayView.isHidden = true;
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

如果我只是从 JavaScript 函数接收字符串,我需要在上面添加什么?

javascript swift uiwebview ios10
3个回答
20
投票

我建议考虑使用

WKWebView
代替
UIWebView
。这样您就不需要注册自定义 URL 方案。此外,UIWebView 已经过时,而 WKWebView 有很多优点,最显着的是性能和渲染,因为它在单独的进程中运行。

Apple 文档的链接和使用 WKWebView 的建议 https://developer.apple.com/reference/webkit/wkwebview/

重要

从 iOS 8.0 和 OS X 10.10 开始,使用 WKWebView 将 Web 内容添加到您的应用程序。不要使用 UIWebView 或 WebView。

也就是说,设置原生 JavaScript 桥非常简单:

import WebKit

final class ViewController: UIViewController, WKScriptMessageHandler {
    private var webView: WKWebView?
    override func loadView() {
        super.loadView()
        
        let webView = WKWebView(frame: self.view.frame)
        webView.configuration.userContentController.add(self, name: "scriptHandler")
        self.webView = webView
        
        self.view.addSubview(webView)
    }
    
    public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        print("Message received: \(message.name) with body: \(message.body)")
    }
    // rest of code
}

然后在您的 javascript 代码中调用它:

window.webkit.messageHandlers["scriptHandler"].postMessage("hello");

我编写了一个库,利用它并添加了一些奇特的 JavaScript 语法。 https://github.com/tmarkovski/BridgeCommander

要使用它,只需引用该项目(或将 swift 和 javascript 文件添加到您的 Xcode 项目中)并调用

webView = WKWebView(frame: self.view.frame)
let commander = SwiftBridgeCommander(webView!)

commander.add("echo") {
    command in
    command.send(args: "You said: \(command.args)")
}

然后您将能够像这样在 javascript 中使用回调语法

var commander = new SwiftBridgeCommander();
commander.call("echo", "Hello", function(args) {
        // success callback
    }, function(error) { 
        // error callback
});

3
投票

您必须自定义

URL Scheme
例如
myawesomeapp
并使用以下方式拦截对其的请求:

func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool

使用

window.location=myawesomeapp://hello=world
发起对本机代码的调用,并获取从本机代码中的
request.URL.query
传递的查询参数。

有关更多信息,请参阅我关于

UIWebView
的问题:JavaScript 与 WKWebView 的同步本机通信


0
投票

我们可以借助 WKScriptMessageHandler

从 Javascript 调用 swift 函数

符合 WKScriptMessageHandler 协议的类提供了从网页上运行的 JavaScript 接收消息的方法。

我们需要将事件监听器添加到 WKUserContentController 中

 let contentController = WKUserContentController()
    contentController.add(self, name: "loginAction”)

我们必须实现它的 userContentController 来接收从 Javascript 发送的内容。对于前。目前仅限于我们想要的“注销”。

  func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {       
       if message.name == "logout" {
           print("JavaScript is sending a message \(message.body)")
       }
   }

从 JavaScript 端来看,他们必须这样实现:

 function sendLogoutAction() {
       try {
           webkit.messageHandlers.logout.postMessage("logout");
       } catch(err) {
           console.log('The native context does not exist yet');
       }
    }
© www.soinside.com 2019 - 2024. All rights reserved.