NEW: Subscribe to Hacking with Swift+ and accelerate your learning! >>

How do a send back the result of an Alert confirmation from ContentView back to a Coordinator of a UIViewRepresentable?

Forums > 100 Days of SwiftUI

Hi,

I have a UIViewRepresentable for a WKWebView which is loaded in ContentView, all is well and I can respond to UI and Navigation delegate methods.

Part of what I want to do is raise Alert when JavaScript raises events (which is handled fine by passing in a couple of Binding and setting the wrappedValue). I am be able to raise Alerts with confirmation buttons in a similar fashion.

The runJavaScriptConfirmPanelWithMessage delegate method called by WKWebView excepts to call completionHandler with a Boolean value which would be the result of what the user tapped on the Alert.

Question What would be the ideal way to bubble back the the resposne from the Alert back to the Coordinator housed in the ContentView ?

Any pointers are very welcome. Thank you for sparing your time to read and respond.

Reference implementation of UIViewRepresentable with Coordinator:

import Foundation
import SwiftUI
import WebKit

struct WebView : UIViewRepresentable {

    let request: URLRequest
    @Binding var showAlert: Bool
    @Binding var alertMessage: String

    // This has to be inside the representable structure
    class Coodinator: NSObject, WKUIDelegate, WKNavigationDelegate {

        var parent: WebView
        var showAlert: Binding<Bool>
        var alertMessage: Binding<String>

        init(_ parent: WebView, showAlert: Binding<Bool>, alertMessage: Binding<String>) {
            self.parent = parent
            self.showAlert = showAlert
            self.alertMessage = alertMessage
        }

        // MARK: - UI Delegate

        func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
            self.alertMessage.wrappedValue = message
            self.showAlert.wrappedValue.toggle()
            completionHandler()
        }

        func webView(_ webView: WKWebView,
                     runJavaScriptConfirmPanelWithMessage message: String,
                     initiatedByFrame frame: WKFrameInfo,
                     completionHandler: @escaping (Bool) -> Void) {
            self.alertMessage.wrappedValue = message
            self.showAlert.wrappedValue.toggle()
            completionHandler(true)
        }

        // MARK: - Navigation Delegate

        func webView(_ webView: WKWebView,
                     decidePolicyFor navigationAction: WKNavigationAction,
                     decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
            decisionHandler(.allow)
        }

    }

    func makeCoordinator() -> Coodinator {
        return Coodinator(self, showAlert: self.$showAlert, alertMessage: self.$alertMessage)
    }

    func makeUIView(context: Context) -> WKWebView  {
        let webview = WKWebView()
        webview.uiDelegate = context.coordinator
        webview.navigationDelegate = context.coordinator
        return webview
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {
        uiView.load(request)
    }
}

and extract from the CotnentView that houses it:

    var body: some View {
        NavigationView {
            VStack {
                WebView(request: URLRequest(url: URL(string: "https://.....")!), showAlert: self.$showAlert, isAlertConfirmation: self.$isAlertConfirmation, alertMessage: self.$alertMessage)
                .alert(isPresented: self.$showAlert) { () -> Alert in
                    var alert = Alert(title: Text(alertMessage))
                    if(self.isAlertConfirmation == true) {
                        alert = Alert(title: Text("Are you Sure?"), message: Text(alertMessage), primaryButton: .default(Text("Confirm"), action: {
                            print("OK")
                        }), secondaryButton: .cancel({
                            print("Cancel")
                        }))
                    }
                    return alert;
                }
            }

   

I have exactly this same problem! Did you manage to find a solution?

   

Hacking with Swift is sponsored by NSSpain

SPONSORED Announcing NSSpain 2020: Remote Edition! An online, continuous conference for iOS developers. We’ll start on Thursday and finish on Friday, with talks, activities, and lots of fun for 36 hours, non-stop. Sound good? Join us!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

Not logged in

Log in
 

Link copied to your pasteboard.