I try to start a second view with the help of the WKWebview by clicking a button. It also works. I get a callback in the function userContentController. How is it possible to start a new view in the app from this function.
struct MyWebView: UIViewRepresentable {
var webPageURL = "https://google.de"
func updateUIView(_ uiView: WKWebView, context: Context) {
let myURL = URL(string:webPageURL)
let myRequest = URLRequest(url: myURL!)
uiView.load(myRequest)
}
func makeUIView(context: Context) -> WKWebView {
let webConfiguration = WKWebViewConfiguration()
let wkcontentController = WKUserContentController()
wkcontentController.add(context.coordinator, name: "doStuffMessageHandler")
webConfiguration.userContentController = wkcontentController
let webView = WKWebView(frame: .zero,configuration: webConfiguration)
context.coordinator.parent = webView // inject as weak
return webView
}
func makeCoordinator() -> ContentController {
ContentController() // let handler be a coordinator
}
}
class ContentController: NSObject, WKScriptMessageHandler {
weak var parent: WKWebView? // weak to avoid reference cycling
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)
{
if message.name == "doStuffMessageHandler"
{
print(message.body)
}
}
}
struct MyWebView_Previews: PreviewProvider {
static var previews: some View {
MyWebView()
}
}
The possible solution is using notifications (which allows keep those components independent).
extension Notification.Name {
static let didReceiveMessage = Notification.Name("didReceiveMessage")
}
class ContentController: NSObject, WKScriptMessageHandler {
weak var parent: WKWebView? // weak to avoid reference cycling
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)
{
if message.name == "doStuffMessageHandler"
{
NotificationCenter.default.post(name: .didReceiveMessage, object: message.body)
}
}
}
struct DemoHandleMessage: View {
@State private var showMessage = false
@State private var message: String? = nil
var body: some View {
VStack {
if showMessage {
// switch back via bound flag to showMessage state
MessageView(text: message, dismiss: $showMessage)
} else {
MyWebView()
}
}.onReceive(NotificationCenter.default.publisher(for: .didReceiveMessage)) { notification in
self.message = notification.object as? String
self.showMessage = true
}
}
}