This article will demonstrate how an iOS app can receive message from a web page. This is in contrast to receiving message or data from backend.
This may come in handy on some particular situations, such as if the page needs to request some UI related properties to improve the presentation of the webpage to the device.
You can download the source code here:.
Step 1 — Setup WKWebView
import UIKit
import WebKit
class ViewController: UIViewController {
private lazy var webView: WKWebView = {
let config = WKWebViewConfiguration()
let webView = WKWebView(frame: .zero, configuration: config)
return webView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(webView)
webView.frame = view.bounds
}
}
Step 2 — Setup WKUserContentController
Add an instance of WKUserContentController to WKWebViewConfiguration instance.
import UIKit
import WebKit
class ViewController: UIViewController {
private lazy var webView: WKWebView = {
let contentController = WKUserContentController()
contentController.add(self, name: "headerInfo")
let config = WKWebViewConfiguration()
config.userContentController = contentController
let webView = WKWebView(frame: .zero, configuration: config)
return webView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(webView)
webView.frame = view.bounds
}
}
extension ViewController: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == "headerInfo" {
print(message.body)
}
}
}
The add(_:name:) method installs a message handler that you can call from your JavaScript code. You can call this through a web page using JavaScript code:
window.webkit.messageHandlers.<name>.postMessage(<messageBody>)
The WKScriptMessageHandler protocol method userContentController(_:didReceive:) will be called whenever the web page sends some message.
Step 3 — Load the web page
You can use any web page as long as it post message through webkit. In this article, I will use a simple web page:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
function postSomeMessage(message) {
window.webkit.messageHandlers.headerInfo.postMessage(message)
}
</script>
</head>
<body>
<input type="button" value="Press me to send 'Apple'" onclick="postSomeMessage('Apple')">
<input type="button" value="Press me to send 'Orange'" onclick="postSomeMessage('Orange')">
<input type="button" value="Press me to send 'Mango'" onclick="postSomeMessage('Mango')">
</body>
</html>
This HTML file is saved on file path:
/Users/dexter/Desktop/knowledge-base-resources-swift-series-/SampleWebpage/index.html
If you are not using pure HTML, and instead use React, Vue, Svelte, etc., you can also do this since all of them produce HTML in the end.
We load the page using the following code and put them on the viewDidLoad:
let url = URL(string: "file:///Users/dexter/Desktop/knowledge-base-resources-swift-series-/SampleWebpage/index.html")
let request = URLRequest(url: url!)
webView.load(request)
The completed app should look like this:
Conclusion
An iOS app receiving message from web page directly, which are both front end clients, will really be helpful. Instead of just displaying the the web page, we can interact with it just like with our native components. Although the means of interaction is through messages, and cannot access the elements directly, this makes interaction simpler in some ways. The web page developer will just tell you that they will be sending something through a message handler, and you deal with it based on your apps requirements.
The next article I will write is about two-way communication between the web page and the iOS app!