Android's WebView affords me the opportunity to add functions that can be called directly from the server. For instance, I can write a function displayToast(message)
this way:
...
// add webapp interface to webview
webView.addJavascriptInterface(new WebAppInterface(), "Android");
// Web app interface
public class WebAppInterface {
// Javascript interface function to display a toast
@JavascriptInterface
public void displayToast(String message) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
}
}
I can then call Android.displayToast()
in my Javascript code (as in the code snippet below) and then have a toast message displayed on the user's screen.
const performOperation = () => {
...
Android.displayToast("The process was successful")
}
I want to implement something exactly like this in a native iOs codebase using Swift. I want to include functions in my Swift WebView that I can call directly from the server. How do I go about this?
You can do this by injecting javascript code into the webview.
Let's say for example we want to get the print of console.log
in our application to display it in our application.
From javascript if you want to send a message to the webkit you must use this window.webkit.messageHandlers.{NAME_TO_IDENTIFY_RECEVEID_MESSAGE}.postMessage({MESSAGE_TO_SEND})
For example window.webkit.messageHandlers.logging.postMessage(MyLog)
You must register this type to the webview:
webView.configuration.userContentController.add(self, name: "logging")
Messages are received in the delegate of WKScriptMessageHandler
:
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
let type = message.name
let message = message.body
print("Received message: \(message) from \(type)")
// Output Received message: MyLog from logging
}
If you have access to the server code you can simply add the code below to override the log function which will send the messages to the webkit:
var console = { log: function(msg){window.webkit.messageHandlers.logging.postMessage(msg) } };
If you don't have access to the server you can inject the javascript code from the webview like this (declared before webView.load (request)
):
let scriptJS = "var console = { log: function(msg){window.webkit.messageHandlers.logging.postMessage(msg) } };"
let logScript = WKUserScript(source: scriptJS, injectionTime: .atDocumentStart, forMainFrameOnly: false)
webView.configuration.userContentController.addUserScript(logScript)
So here I explained to you how it works here, we taken the example of handle the console.log
.
The most important thing to remember is that you can send messages via window.webkit.messageHandlers.{NAME_TO_IDENTIFY_RECEVEID_MESSAGE}.postMessage({MESSAGE_TO_SEND})
and handle it here func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)