-
-
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) {
// ...
}
Amazing work, very useful!
FYI: Some reason my coordinators webView was nil and had to be set elsewhere...
@JSerZANP thanks for the script!