Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WKWebView doesn't run JavaScript when on background

I noticed that sometimes when the webview is moved to background (have another view controller on top), it stops JavaScript functions execution, and executes them only when returning back to foreground.
here a thread with a similar issue but most of the solutions was some kind of hack, like adding the webview to the key window, or looping dummy calls to evaluateJavaScript so the webview wouldn't go to idle mode and stop JavaScript.
Those solutions work btw, but I don't like them at all.
I was wondering if there was a better solution for this problem, any way to configure the webView to prevent going into idle mode, or more elegant way to prioritize JavaScript.
Thanks.

like image 522
ItayAmza Avatar asked Nov 26 '18 13:11

ItayAmza


1 Answers

Unfortunately, WKWebView must be in the view hierarchy to use it. You must have added it as a sub view of an on-screen view controller.

You can add this off-screen so it was not visible. Hidden attribute might have worked as well. Either way you must call addSubview with it to make it work.

There are some other questions and answers here which verify this.

So, I researched a lit bit a found this

WKWebViewConfiguration* webViewConfig = // set up config

// provide empty frame rect
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero 
configuration:webViewConfig];

// add to keyWindow to ensure it is 'active'
[UIApplication.sharedApplication.keyWindow addSubview:webView];

This approach at least ensures the javascript runs while the app is active and doesn't effect the UI. If you need to display it later you can remove the webView from the keyWindow after render and reset the frame.

Hope this helps!

EDIT

Javascript is disabled by default. In order to run Javascript, you must enable it through WKPreferences. You need to set the javascriptEnabled field of the preferences object to true.

Specifically your code to initialize the WKWebView should look like this.

let contentController = WKUserContentController()
contentController.add(self, name: "handler") 

let configuration = WKWebViewConfiguration()
configuration.userContentController = contentController
configuration.preferences = WKPreferences()
configuration.preferences.javaScriptEnabled = true

webview = WKWebView(frame: self.view.frame, configuration: configuration)
webview.uiDelegate = self
webview.navigationDelegate = self
self.view = self.webview

Also you can check this post to see a different approach.

like image 164
Ömürcan Cengiz Avatar answered Oct 21 '22 04:10

Ömürcan Cengiz