Wednesday, June 12, 2024
HomeiOS Developmentjavascript - SwiftUI internet view does not present up the primary time

javascript – SwiftUI internet view does not present up the primary time


It is best to anticipate the net view to complete loading the HTML first, earlier than calling the render operate in JS.

It is best to use the didFinish delegate methodology in WKNavigationDelegate to detect that the net view has completed loading. Then you possibly can invoke a callback that’s handed to the TestView.

struct TestView: UIViewRepresentable {
    let htmlPath: String
    @Binding var state: MyState
    let didLoad: () -> Void
    
    class Coordinator: NSObject, WKNavigationDelegate {
        var didLoad: () -> Void
        
        init(didLoad: @escaping () -> Void) {
            self.didLoad = didLoad
        }
        
        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            // if the net view will load a number of pages, 
            // add a flag and test it right here in order that didLoad solely will get known as as soon as
            didLoad()
        }
    }
    
    func makeCoordinator() -> Coordinator {
        .init(didLoad: didLoad)
    }
    
    func makeUIView(context: Context) -> WKWebView {
        let webView = WKWebView()
        webView.navigationDelegate = context.coordinator
        if let htmlPath = Bundle.fundamental.path(forResource: htmlPath, ofType: "html") {
            do {
                let htmlString = attempt String(contentsOfFile: htmlPath)
                webView.loadHTMLString(htmlString, baseURL: Bundle.fundamental.bundleURL)
                webView.scrollView.showsHorizontalScrollIndicator = true
                print("TestView.makeUIView: Completed inital loading.")
            } catch {
                print("TestView.makeUIView: Error loading HTML file: (error)")
            }
        }
        return webView
    }
    
    func updateUIView(_ webView: WKWebView, context: Context) {
        context.coordinator.didLoad = didLoad
        let script = "render('(state.textual content)');"
        webView.evaluateJavaScript(script) { _, error in
            if let error = error {
                print("TestView.updateUIView error: (error)")
            }
        }
    }
}

As an alternative of onAppear, it’s best to set the @State within the didLoad closure:

@State personal var state = MyState(textual content: "") // the preliminary worth right here is only a "dummy"

var physique: some View {
    TestView(htmlPath: "foo", state: self.$state) {
        // set it to the preliminary worth you need right here
        state.textual content = "whats up testview"
        DispatchQueue.fundamental.asyncAfter(deadline: .now() + 5.0) {
            state.textual content = "hello2 testview"
        }
    }
}

Observe that it will nonetheless print the error you noticed, as a result of the net view is not going to have completed loading when updateUIView is named for the primary time, nevertheless it does not matter. That is simply failing to run render('') (the preliminary dummy empty string). updateUIView will probably be known as once more to run render('whats up testview'), after the net view finishes loading the HTML.


P.S. I hope this render operate is only a dummy operate you wrote for the minimal reproducible instance, and that your actual code isn’t like this. You aren’t sanitising the parameter of render in any respect, and it is a big code injection vulnerability.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments