1
votes

I'm working on SwiftUI, but since there is not a WKWebView I created it through a UIViewRepresentable.

This is some code:

func makeUIView(context: Context) -> WKWebView {

    let jsScript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);"

    let userScript = WKUserScript(source: jsScript, injectionTime: .atDocumentEnd, forMainFrameOnly: true)

    let wkController = WKUserContentController()

    wkController.addUserScript(userScript)

    let wkWebConfiguration = WKWebViewConfiguration()

    wkWebConfiguration.userContentController = wkController

    let webView = WKWebView(frame: .null, configuration: wkWebConfiguration)

    webView.translatesAutoresizingMaskIntoConstraints = false

    webView.loadHTMLString(htmlBody, baseURL: nil)
    
    return webView
}

func updateUIView(_ uiView: WKWebView, context: Context) {
    
    if let htmlBody = self.htmlBody {
        uiView.loadHTMLString(htmlBody, baseURL: nil)
    }

}

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

What I need to do is to scroll to the bottom of it on button click.

So in my SwiftUI View I have a @State var and I pass it to my UIViewRepresentable.

This is what I tried (inside my updateUIView):

  if scrollWebView {
        let scrollPoint = CGPoint(x: 0, y: yourWebView.scrollView.contentSize.height - webView.frame.size.height)
        webView.scrollView.setContentOffset(scrollPoint, animated: true)
  }

But this code (on button click) scroll to the top of my WkWebView. Even if I change the sign of the y. It always scroll to the top instead of the bottom.

I dont think I can achieve this in my SwiftUI View, and I can't find a way to scroll to the bottom of my WKWebView.

I do also think the behavior (since I can do webView.scrollView) is quiete similar to a ScrollView.

Any help?

1

1 Answers

1
votes

Here is a simplified demo of possible approach. Tested with Xcode 12 / iOS 14.

struct DemoWebView : UIViewRepresentable {
    let text: String
    @Binding var scrollToBottom: Bool

    func makeUIView(context: Context) -> WKWebView  {
        let webview = WKWebView()
        webview.loadHTMLString(text, baseURL:  nil)
        return webview
    }

    func updateUIView(_ webview: WKWebView, context: Context) {
        if scrollToBottom {
            let point = CGPoint(x: 0, y: webview.scrollView.contentSize.height - webview.frame.size.height)
            webview.scrollView.setContentOffset(point, animated: true)
            DispatchQueue.main.async {
                self.scrollToBottom = false   // turn it back for reuse
            }
        }
    }
}

and usage like

@State private var scroll = false

var body: some View {
    VStack {
        Button("Bottom") { self.scroll = true }
        DemoWebView(text: self.htmlText, scrollToBottom: $scroll)
    }
}