-
-
Save JSerZANP/ea300d419bfafa79e4f8c0af42d8fec6 to your computer and use it in GitHub Desktop.
import SwiftUI | |
import WebKit | |
struct WebView: UIViewRepresentable { | |
class Coordinator: NSObject, WKNavigationDelegate, WKScriptMessageHandler { | |
var webView: WKWebView? | |
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { | |
self.webView = webView | |
} | |
// receive message from wkwebview | |
func userContentController( | |
_ userContentController: WKUserContentController, | |
didReceive message: WKScriptMessage | |
) { | |
print(message.body) | |
let date = Date() | |
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { | |
self.messageToWebview(msg: "hello, I got your messsage: \(message.body) at \(date)") | |
} | |
} | |
func messageToWebview(msg: String) { | |
self.webView?.evaluateJavaScript("webkit.messageHandlers.bridge.onMessage('\(msg)')") | |
} | |
} | |
func makeCoordinator() -> Coordinator { | |
return Coordinator() | |
} | |
func makeUIView(context: Context) -> WKWebView { | |
let coordinator = makeCoordinator() | |
let userContentController = WKUserContentController() | |
userContentController.add(coordinator, name: "bridge") | |
let configuration = WKWebViewConfiguration() | |
configuration.userContentController = userContentController | |
let _wkwebview = WKWebView(frame: .zero, configuration: configuration) | |
_wkwebview.navigationDelegate = coordinator | |
return _wkwebview | |
} | |
func updateUIView(_ webView: WKWebView, context: Context) { | |
guard let path: String = Bundle.main.path(forResource: "index", ofType: "html") else { return } | |
let localHTMLUrl = URL(fileURLWithPath: path, isDirectory: false) | |
webView.loadFileURL(localHTMLUrl, allowingReadAccessTo: localHTMLUrl) | |
} | |
} | |
struct ContentView: View { | |
var body: some View { | |
VStack { | |
Text("hello?") | |
WebView() | |
} | |
} | |
} | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, minimum-scale=1, viewport-fit=cover"> | |
</head> | |
<body> | |
<button>click me</button> | |
<hr/> | |
<div id="log"></div> | |
<script> | |
const log = (msg) => { | |
const p = document.createElement('p') | |
p.textContent = msg | |
document.querySelector('#log').append(p) | |
} | |
// to receive messages from native | |
webkit.messageHandlers.bridge.onMessage = (msg) => { | |
log('from native:' + msg) | |
} | |
document.querySelector('button').addEventListener('click', () => { | |
log(typeof webkit.messageHandlers.bridge.postMessage) | |
// send messages to native | |
webkit.messageHandlers.bridge.postMessage('{"msg": "hello?","id": ' + Date.now() + '}') | |
}) | |
</script> | |
</body> | |
</html> | |
Thanks dude, really good and clean code! Nice job!
Thanks, it works!
Thanks!
The best example I've found so far. Great job!
Excuse me, I have a problem. In line 17. "print(message.body)". When I build I can get msg and id's information.
How can I get the "msg" information only and I need to store it to "MSG" to use.
Thanks! This helps out a ton
func makeCoordinator
automatically executed before makeUIView
, so there must be
func makeUIView(context: Context) -> WKWebView {
------> let coordinator = context.coordinator <-------
let userContentController = WKUserContentController()
userContentController.add(coordinator, name: "bridge")
.....
return _wkwebview
}
// to receive messages from native
webkit.messageHandlers.bridge.onMessage = (msg) => {
log('from native:' + msg)
}
There is a problem when handling SwiftUI's javascript instructions
First, initialization is good, but then when I update the view I get an error
WKJavaScriptExceptionLineNumber=1, WKJavaScriptExceptionMessage=TypeError: webkit.messageHandlers.bridge.onMessage is not a function.
Finally I used other people's method to solve it
https://stackoverflow.com/a/56325336/12679246
window.onMessage = function(msg) {
// ...
}
@JSerZANP thanks for the script!