SwiftUI how to wrap WKWebView to make it autosizing after html load

951 views Asked by At

I have WKWebView placed in List cell and want this cell to be autosized to height of content that was loaded into WKWebView. I have tried such code but it doesn't work

struct WebView: UIViewRepresentable {

    let url: URL?
    let html: String?

    let didFail: (WKNavigation) -> Void
    let didFinish: (WKNavigation) -> Void

    @Binding var contentHeight : CGFloat

    init(html: String, contentHeight: Binding<CGFloat> = .constant(0), didFail: @escaping (WKNavigation) -> Void = { _ in }, didFinish: @escaping (WKNavigation) -> Void = { _ in }) {
        self.url = nil
        self.html = html

        self.didFinish = didFinish
        self.didFail = didFail

        self._contentHeight = contentHeight
    }

    init(url: URL, contentHeight: Binding<CGFloat> = .constant(0), didFail: @escaping (WKNavigation) -> Void = { _ in }, didFinish: @escaping (WKNavigation) -> Void = { _ in }) {
        self.url = url
        self.html = nil

        self.didFinish = didFinish
        self.didFail = didFail

        self._contentHeight = contentHeight
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: Context) -> WKWebView {

        let webView = WKWebView()
        webView.navigationDelegate = context.coordinator
        webView.uiDelegate = context.coordinator

        if let url = url {
            let request = URLRequest(url: url)
            webView.load(request)
        } else if let html = html {
            webView.loadHTMLString(html, baseURL: nil)
        }

        return webView
    }

    func updateUIView(_ webView: WKWebView, context: Context) {

    }

    class Coordinator : NSObject, WKNavigationDelegate, WKUIDelegate {

        private let parent: WebView

        init(_ parent: WebView) {
            self.parent = parent
        }

        func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {

            parent.didFail(navigation)
        }

        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            webView.evaluateJavaScript("document.readyState", completionHandler: { (ready, error) in
                if ready != nil {
                    webView.evaluateJavaScript("document.documentElement.scrollHeight", completionHandler: { (height, error) in

                        if let contentHeight = height as? CGFloat {
                            self.parent.contentHeight = contentHeight
                        }
                    })
                }
            })

            parent.didFinish(navigation)
        }

    }
}

Even setting .frame(height: contentHeight) via @State does not work.

0

There are 0 answers