I am new in SwiftUI I have created WebView like this in SwiftUI
struct WebView: UIViewRepresentable {
@Binding var title: String
var url: URL
var loadStatusChanged: ((Bool, Error?) -> Void)? = nil
func makeCoordinator() -> WebView.Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> WKWebView {
let view = WKWebView()
view.navigationDelegate = context.coordinator
view.load(URLRequest(url: url))
return view
}
func updateUIView(_ uiView: WKWebView, context: Context) {
// you can access environment via context.environment here
// Note that this method will be called A LOT
}
func onLoadStatusChanged(perform: ((Bool, Error?) -> Void)?) -> some View {
var copy = self
copy.loadStatusChanged = perform
return copy
}
class Coordinator: NSObject, WKNavigationDelegate,WKScriptMessageHandler {
@State private var studentAppID = UserDefaults.standard.string(forKey: "studentAppID")
let parent: WebView
init(_ parent: WebView) {
self.parent = parent
}
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
print(webView.url as Any)
parent.loadStatusChanged?(true, nil)
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print(webView as Any)
print(webView.url as Any)
parent.title = webView.title ?? ""
webView.evaluateJavaScript("document.getElementsByName('applnID')[0].value='\(studentAppID!)'", completionHandler: nil)
parent.loadStatusChanged?(false, nil)
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
parent.loadStatusChanged?(false, error)
}
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
// guard let dict = message.body as? [String : AnyObject] else {
// return
// }
print(message.body)
}
}
}
I want to configure function so that I can received response from WebView when user click on the button tag on the WebView
I found the code for this in swift but don't understand how can I used it in SwiftUI
The code is like this
class ViewController: UIViewController, WKScriptMessageHandler {
let content = """
<!DOCTYPE html><html><body>
<button onclick="onClick()">Click me</button>
<script>
function onClick() {
window.webkit.messageHandlers.backHomePage.postMessage("success");
}
</script>
</body></html>
"""
override func viewDidLoad() {
super.viewDidLoad()
let config = WKWebViewConfiguration()
config.userContentController = WKUserContentController()
config.userContentController.add(self, name: "backHomePage")
let webView = WKWebView(frame: CGRect(x: 0, y: 0, width: 200, height: 200), configuration: config)
view.addSubview(webView)
webView.loadHTMLString(content, baseURL: nil)
}
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
print(message.body)
}
}
as flow in this link
How to receive callback in ios from javascript?
Can I configure same in SwiftUI if yes then how?
What you have implemented is correct however you have missed out on WKWebViewConfiguration
object.
You need to create web view configuration that registers a message handler for your javascript code to call, see below:
Create a class that can receive callbacks from JavaScript code:
let scriptMessageHandler = ScriptMessageHandler()
class ScriptMessageHandler: NSObject, WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
print(message.body)
}
}
Create a config object and pass an object of ScriptMessageHandler
as handler.
let config = WKWebViewConfiguration()
config.userContentController = WKUserContentController()
config.userContentController.add(scriptMessageHandler, name: "backHomePage")```
You can do this in your makeUIView(context:) -> WKWebView
method implementation, right before you create Web View object and pass this config to your web view.
In Javascript, above config can then be called like below:
function onClick() {
window.webkit.messageHandlers.backHomePage.postMessage("success");
}
When above function is called from JavaScript, you will get a callback in your userContentController(_ didReceive:)
implementation.