Search code examples
swiftwebviewswiftuiwkwebview

ios: How to reload webview from a Coordinator class SwiftUi


I am making an app that contains multiple web-view's. I am wanting to reload my web-view from the coordinator class after a JS command is sent from the webpage and inside the "func processReturnedJS(body: String)" shown below. I am wondering how I can achieve this in a simple way?

Thanks

SubscriptionViewController:

import SwiftUI
import WebKit

struct SubscriptionViewController: UIViewRepresentable {
    @StateObject var storeManager: StoreManager
    
    let frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
    let config = WKWebViewConfiguration()
    let cookies = HTTPCookieStorage.shared.cookies ?? []
    
    func makeUIView(context: UIViewRepresentableContext<SubscriptionViewController>) -> WKWebView {
        for cookie in cookies {
            config.websiteDataStore.httpCookieStore.setCookie(cookie, completionHandler: nil)
        }
        
        let preferences = WKPreferences()
        
        let configuration = WKWebViewConfiguration()
        configuration.preferences = preferences
        
        let userContentController = WKUserContentController()
        
        userContentController.add(context.coordinator, name:"observer")
        
        configuration.userContentController = userContentController
        
        
        let view = WKWebView(frame: frame, configuration: configuration)
        view.navigationDelegate = context.coordinator
        
        DispatchQueue.main.async {
            let url = URL(string:"theurl")!
            let request = URLRequest(url: url)
            for cookie in cookies {
                config.websiteDataStore.httpCookieStore.setCookie(cookie, completionHandler: nil)
                view.configuration.websiteDataStore.httpCookieStore.setCookie(cookie, completionHandler: nil)
            }
            
            view.load(request)
        }
        
        return view
    }
    
    func updateUIView(_ uiView: WKWebView, context: UIViewRepresentableContext<SubscriptionViewController>) {

    }
    
    func makeCoordinator() -> CoordinatorSubscription {
        CoordinatorSubscription(self, storeManage: self.storeManager)
    }
    
    typealias UIViewType = WKWebView
}


class CoordinatorSubscription: NSObject, WKNavigationDelegate, WKScriptMessageHandler {
    
    var control: SubscriptionViewController
    var storeManage: StoreManager

    init(_ control: SubscriptionViewController, storeManage: StoreManager) {
        self.control = control
        self.storeManage = storeManage
    }
    
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        processReturnedJS(body: message.body as! String)
    }
    
    func sendjs(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    }
    
    
    
    
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        
    }

    
    
    func processReturnedJS(body: String) {
    
        print("kkkk")
        
        //want to reload webview from here
            

    }
}


Solution

  • You can store a reference to the WKWebView in your coordinator:

    class CoordinatorSubscription: NSObject, WKNavigationDelegate, WKScriptMessageHandler {
        
        var control: SubscriptionViewController
        var storeManage: StoreManager
        var webView : WKWebView? //<-- Here
    
        init(_ control: SubscriptionViewController, storeManage: StoreManager) {
            self.control = control
            self.storeManage = storeManage
        }
        
        func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
            processReturnedJS(body: message.body as! String)
        }
        
        func sendjs(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        }
        
        
        
        
        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            
        }
    
        
        
        func processReturnedJS(body: String) {
        
            self.webView?.reload() //here
    
        }
    }
    

    Then, make sure to set that property in makeUIView:

    func makeUIView(context: UIViewRepresentableContext<SubscriptionViewController>) -> WKWebView {
        for cookie in cookies {
            config.websiteDataStore.httpCookieStore.setCookie(cookie, completionHandler: nil)
        }
        
        let preferences = WKPreferences()
        
        let configuration = WKWebViewConfiguration()
        configuration.preferences = preferences
        
        let userContentController = WKUserContentController()
        
        userContentController.add(context.coordinator, name:"observer")
        
        configuration.userContentController = userContentController
        
        
        let view = WKWebView(frame: frame, configuration: configuration)
        view.navigationDelegate = context.coordinator
        
        DispatchQueue.main.async {
            let url = URL(string:"theurl")!
            let request = URLRequest(url: url)
            for cookie in cookies {
                config.websiteDataStore.httpCookieStore.setCookie(cookie, completionHandler: nil)
                view.configuration.websiteDataStore.httpCookieStore.setCookie(cookie, completionHandler: nil)
            }
            
            view.load(request)
        }
        
        context.coordinator.webView = view //<-- Here
        
        return view
    }