evaluateJavaScript in swiftui

拥有回忆 提交于 2020-04-16 03:32:09

问题


How to get evaluateJavaScript to work when a message is received from webview?

print(message.body) <--- this is working

parent?.evaluateJavaScript("document.getElementsByClassName('mat-toolbar-single-row')[0].style.backgroundColor = 'red'", completionHandler: nil) <--- this is not

struct WebView: UIViewRepresentable {

let request: URLRequest

let contentController = ContentController(nil)


func makeUIView(context: Context) -> WKWebView {
    let webConfiguration = WKWebViewConfiguration()
    let wkcontentController = WKUserContentController()
    wkcontentController.add(contentController, name: "test")
    webConfiguration.userContentController = wkcontentController
    return WKWebView(frame: .zero, configuration: webConfiguration)
}



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

class ContentController: NSObject, WKScriptMessageHandler {
    var parent: WKWebView?
    init(_ parent: WKWebView?) {
        self.parent = parent
    }

    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)  {
        if message.name == "test"{
            print(message.body)
            parent?.evaluateJavaScript("document.getElementsByClassName('mat-toolbar-single-row')[0].style.backgroundColor = 'red'", completionHandler: nil)

        }
    }
}

回答1:


Here is possible approach. As I don't have intended testing environment I could not test it completely, but all infrastructure constructed correctly. So you can try

struct WebView: UIViewRepresentable {

    let request: URLRequest

    func makeUIView(context: Context) -> WKWebView {
        let webConfiguration = WKWebViewConfiguration()
        let wkcontentController = WKUserContentController()

        wkcontentController.add(context.coordinator, name: "test")
        webConfiguration.userContentController = wkcontentController

        let webView = WKWebView(frame: .zero, configuration: webConfiguration)
        context.coordinator.parent = webView // inject as weak

        return webView
    }

    func updateUIView(_ view: WKWebView, context: Context) {
        if view.url == nil {
            view.load(request)
        }
    }

    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 == "test" {
                print(message.body)
                parent?.evaluateJavaScript("document.getElementsByClassName('mat-toolbar-single-row')[0].style.backgroundColor = 'red'", 
                    completionHandler: nil)

            }
        }
    }
}



回答2:


The answer is to pass WKWebview to ContentController() instead of nil

Here is a working example;

struct WebView: UIViewRepresentable {

let request: URLRequest

func makeUIView(context: Context) -> WKWebView {
            return WKWebView()
}



func updateUIView(_ view: WKWebView, context: Context) {
    let contentController = ContentController(view)
    let userScript = WKUserScript(source: "document.getElementsByClassName('mat-toolbar-single-row')[0].style.backgroundColor = 'black'; alert('from iOS')", injectionTime: WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: true)
    view.configuration.userContentController.add(contentController, name: "test")
    view.configuration.userContentController.addUserScript(userScript)
    view.evaluateJavaScript("document.body.style.backgroundColor = '#4287f5';", completionHandler: nil)
    view.load(request)
}

class ContentController: NSObject, WKScriptMessageHandler {

    var parent: WKWebView?
    init(_ parent: WKWebView?) {
        self.parent = parent
    }

    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)  {
        parent?.evaluateJavaScript("document.getElementsByClassName('mat-toolbar-single-row')[0].style.backgroundColor = 'red';", completionHandler: nil)
            print("from test")
    }
}
}


来源:https://stackoverflow.com/questions/60142384/evaluatejavascript-in-swiftui

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!