With the code below, I'm trying to load HTML into a WKWebview, then scroll it to a particular element.
let url = Bundle.main.url(forResource: "TestHTML", withExtension: "html")!
myWebView.loadFileURL(url, allowingReadAccessTo: url)
myWebView.evaluateJavaScript("document.getElementById('4').scrollIntoView(true);") {[weak self] (result, error) in
print("result: \(result)")
print (error)
}
However, when I run it, the page loads, scrolls to the section, but then jumps back to the top of the page.
I have also tried setting the contentOffset
of the scrollView
, resulting in the exact same issue
I published this question a few months ago, and while this answer worked for a demo project, it wouldn't work for me in another project - it would go to the offset, then just go back to the top.
The issue seems to be that while when the code in webView(didFinish)
runs, the web view has indeed finished loading, but the scroll view has not finished loading.
My solution is as follows:
WKWebViewNavigationDelegate
and UIScrollViewDelegate
protocolsclass ViewController: UIViewController, WKNavigationDelegate, UIScrollViewDelegate {
//..
}
var position: CGPoint?
var webViewFinished = false
didFinish
delegate method, set the value of position
to the scroll view's content offset, and set webViewFinished
to true
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
position = myWebView.scrollView.contentOffset
webViewFinished = true
}
scrollViewDidScroll
delegate method, check if the Web View has finished loading. If it has, set the Scroll View's content offset to the value of position
, and set webViewFinished
to false
(since otherwise, this code will run each time the user scrolls). Don't forget to do optional chaining on position
as well!func scrollViewDidScroll(_ scrollView: UIScrollView) {
if webViewFinished {
webViewFinished = false
if let p = position {
web.scrollView.setContentOffset(p, animated: false)
}
}
}
override func viewDidLoad(){
super.viewDidLoad()
myWebView.navigationDelegate = self
myWebView.scrollView.delegate = self
}