My goal is to hide my application's embedded WKWebView until certain page elements (e.g. header and footer) are removed from the DOM.
My current process looks like this (see code snippets below):
didStartProvisionalNavigation
hook).didFinish navigation
hook, setting the WKWebView to visible in the completion handler.override func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
webView.isHidden = true
}
override func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
var scriptContent = ""
do {
scriptContent = try String(contentsOfFile: GlobalVariables.mainScriptURL!, encoding: String.Encoding.utf8)
} catch {
print("Error loading JavaScript file.")
}
webView.evaluateJavaScript(scriptContent, completionHandler: { result, error in
webView.isHidden = false
})
}
GlobalVariables.mainScriptURL
contents:
$('header').hide();
$('footer').hide();
When the above code executes, I still occasionally see the header prior to its removal. Is there a delay between my JavaScript updating the DOM and the WKWebView redrawing its content that I'm failing to consider? How can I ensure that the content is never visible to my users prior to that JavaScript running and completely removing those elements from the DOM?
Yeah, unfortunately, I have also noticed that WKWebView's web content process painting is not necessarily synchronized with the callbacks in your app. You can get a brief flash of incorrect content before the painting occurs.
The way I'd suggest fixing this is by injecting JavaScript that listens to the DOMContentLoaded event, and does its reformatting work, all within the web content process.
If you own the content being loaded, great, you can just add a <script>
to the <head>
.
If you don't own the source document, you can look into WKUserScript and WKUserContentController, that should allow you to add your own JavaScript without modifying the page source.