swiftswiftuiwkwebviewuiviewrepresentablewkwebviewconfiguration

How to pass a string inside a class that is inside a struct?


struct WebView: UIViewRepresentable {   
    @Binding var response: String
    
    func makeUIView(context: Context) -> WKWebView {
        let webConfiguration = WKWebViewConfiguration()
        let wkController = WKUserContentController()
        
        wkController.add(context.coordinator, name: "reCaptchaiOS")
        webConfiguration.userContentController = wkController
        .....
    }
 
    func updateUIView(_ webView: WKWebView, context: Context) {
        ....
        }
    }
    
    func makeCoordinator() -> ContentController {
        ContentController()// let handler be a coordinator
        }
    
    class ContentController: NSObject, WKScriptMessageHandler {
           .....
        var textResponse: String = ""
            func userContentController(_ userContentController: WKUserContentController,
                                       didReceive message: WKScriptMessage)  {
                if let args = message.body as? [String] {  
                    switch args[0] {         
               .....
                    case "didSolve":
                        self.captchaDidSolve(response: args[1])
                        textResponse = args[1]
                        break
                        
                  .....
                    default:
                        print("args[0]: \(args[0])")
                        break
                        
             ....
            }
                
        func captchaDidSolve(response: String) {
            print("response: \(response)")
            
        }

I need to pass the response that is inside the class ContentController to the response of the structure WebView to use it in a main contentView.


Solution

  • You can store a reference to WebView in ContentController and then access response of WebView in ContentController. For example:

    struct WebView: UIViewRepresentable {
        @Binding var response: String
        
        func makeUIView(context: Context) -> WKWebView {
            let webConfiguration = WKWebViewConfiguration()
            let wkController = WKUserContentController()
            
            wkController.add(context.coordinator, name: "reCaptchaiOS")
            webConfiguration.userContentController = wkController
            // .....
        }
        
        func updateUIView(_ webView: WKWebView, context: Context) {
            // ....
        }
        
        func makeCoordinator() -> ContentController {
            ContentController(parent: self)// let handler be a coordinator
        }
    }
    
        
    class ContentController: NSObject, WKScriptMessageHandler {
        let parent: WebView
        
        init(parent: WebView) {
            self.parent = parent
        }
        
        // .....
        func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)  {
            if let args = message.body as? [String] {
                switch args[0] {
                    // .....
                case "didSolve":
                    self.captchaDidSolve(response: args[1])
                    break
                    
                    // .....
                default:
                    print("args[0]: \(args[0])")
                    break
                    
                    // ....
                }
            }
        }
        
        func captchaDidSolve(response: String) {
            parent.response = response
        }
    }
    

    Now that I think about it though, I don't know why parent is actually a reference when it's a struct. But it seems to work.