I'm trying to make my javascript interact with swift code but unfortunately i didn't succeed.
For the moment, i just tried to change the headers colors and display a message like you will see in the code below.
Here's my (index.html) code:
<!DOCTYPE html> <html> <head> <title>Test</title> <meta charset="UTF-8"> </head> <body> <h1>WebView Test</h1> <script type="text/javascript" src="main.js"></script> </body> </html>
Here's my (main.js -JavaScript) code:
function callNativeApp () { try { webkit.messageHandlers.callbackHandler.postMessage("Send from JavaScript"); } catch(err) { console.log('error'); } } setTimeout(function () { callNativeApp(); }, 5000); function redHeader() { document.querySelector('h1').style.color = "red"; }
Here's my (ViewController.swift) code:
import UIKit import WebKit class ViewController: UIViewController, WKScriptMessageHandler { @IBOutlet var containerView : UIView! = nil var webView: WKWebView? override func loadView() { super.loadView() var contentController = WKUserContentController(); var userScript = WKUserScript( source: "redHeader()", injectionTime: WKUserScriptInjectionTime.AtDocumentEnd, forMainFrameOnly: true ) contentController.addUserScript(userScript) contentController.addScriptMessageHandler( self, name: "callbackHandler" ) var config = WKWebViewConfiguration() config.userContentController = contentController self.webView = WKWebView() self.view = self.webView! } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. var url = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("index", ofType: "html")!) var req = NSURLRequest(URL: url) self.webView!.loadRequest(req) } func userContentController(userContentController: WKUserContentController!,didReceiveScriptMessage message: WKScriptMessage!) { if(message.name == "callbackHandler") { println("JavaScript is sending a message \(message.body)") } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }
The JavaScriptCore framework provides the ability to evaluate JavaScript programs from within Swift, Objective-C, and C-based apps. You can use also use JavaScriptCore to insert custom objects into the JavaScript environment.
Swift code is compiled into machine code. Thus your compiled Swift program can be run as a standalone program - A user doesn't need to have Swift or Xcode installed to run your compiled Swift program.
You have everything set up properly, but you aren't giving your WKWebViewConfiguration
instance to the WKWebView
. Since the configuration has the details of the Javascript/Swift bridge, you can't talk back and forth.
override func loadView() { // ... var config = WKWebViewConfiguration() config.userContentController = contentController self.webView = WKWebView(frame: self.view.frame, configuration: config) self.view = self.webView! }
my 2 cents, using a javascript callback with JSON ... for full class definition and layout, refer to adam's code
import UIKit import WebKit class ViewController: UIViewController, WKScriptMessageHandler { var webView: WKWebView? ...
then
override func loadView() { let theConfiguration = WKWebViewConfiguration() let contentController = theConfiguration.userContentController // alert fix, at start to allow a JS script to overwrite it contentController.addUserScript( WKUserScript( source: "window.alert = function(message){window.webkit.messageHandlers.messageBox.postMessage({message:message});};", injectionTime: WKUserScriptInjectionTime.AtDocumentStart, forMainFrameOnly: true ) ) contentController.addScriptMessageHandler(self, name: "messageBox") self.webView = WKWebView(frame: self.view.frame, configuration: theConfiguration) // and here things like: self.webView!.navigationDelegate = self self.view = self.webView! // fill controllers view }
and specifically
func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) { if message.name == "messageBox" { let sentData = message.body as! Dictionary<String, String> let message:String? = sentData["message"] let alertController = UIAlertController(title: nil, message: message, preferredStyle: UIAlertControllerStyle.Alert) alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment:"btnOK"), style: .Default, handler: nil)) self.presentViewController(alertController, animated: true) {} } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With