问题
I am trying to make a call from a javascript function in a UIWebView to Swift in iOS 10. I have setup a very basic project just to try and get this working, the code is below.
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()
}
}
If I just one to receive a string from a javascript function what would I have to add to the above?
回答1:
You must a custom URL Scheme such as myawesomeapp and intercept requests to it using:
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool
Fire a call to native code using window.location=myawesomeapp://hello=world, and get the query params you pass from request.URL.query in the native code.
For more information, see my question about UIWebViews here: JavaScript synchronous native communication to WKWebView
回答2:
I would suggest looking into using WKWebView instead UIWebView. You then won't need to register custom URL scheme. Additionally, UIWebView is obsolete and WKWebView has a lot of advantages, most notably performance and rendering as it runs in a separate process.
Link to Apple documentation and recommendation to use WKWebView https://developer.apple.com/reference/webkit/wkwebview/
Important
Starting in iOS 8.0 and OS X 10.10, use WKWebView to add web content to your > app. Do not use UIWebView or WebView.
That said, it's very simple to setup a native to javascript bridge:
import WebKit
class ViewController: UIViewController, WKScriptMessageHandler {
var webView: WKWebView?
override func loadView() {
super.loadView()
webView = WKWebView(frame: self.view.frame)
webView?.configuration.userContentController.add(self, name: "scriptHandler")
self.view.addSubview(webView!)
}
public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
print("Message received: \(message.name) with body: \(message.body)")
}
// rest of code
}
Then in your javascript code, call it:
window.webkit.messageHandlers["scriptHandler"].postMessage("hello");
I have written a library that leverages this and adds some fancy javascript syntax. https://github.com/tmarkovski/BridgeCommander
To use it, just reference the project (or add the swift and javascript files to your Xcode project) and call
webView = WKWebView(frame: self.view.frame)
let commander = SwiftBridgeCommander(webView!)
commander.add("echo") {
command in
command.send(args: "You said: \(command.args)")
}
You then will be able to use callback syntax in javascript like this
var commander = new SwiftBridgeCommander();
commander.call("echo", "Hello", function(args) {
// success callback
}, function(error) {
// error callback
});
回答3:
We can call the swift function from Javascript with the help of WKScriptMessageHandler
A class conforming to the WKScriptMessageHandler protocol provides a method for receiving messages from JavaScript running on a webpage.
we need to add a listener to the event into our WKUserContentController
let contentController = WKUserContentController()
contentController.add(self, name: "loginAction”)
We have to implement its userContentController to receive the content sent from Javascript. for ex. limiting only to the "logout" we want for now.
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == "logout" {
print("JavaScript is sending a message \(message.body)")
}
}
And from JavaScript end, They have to implement like this:
function sendLogoutAction() {
try {
webkit.messageHandlers.logout.postMessage("logout");
} catch(err) {
console.log('The native context does not exist yet');
}
}
来源:https://stackoverflow.com/questions/40761218/javascript-call-to-swift-from-uiwebview