25

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.

ItayAmza
  • 819
  • 9
  • 21

1 Answers1

10

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.

Ömürcan Cengiz
  • 2,085
  • 3
  • 22
  • 28
  • Thanks for the links! Could you expand upon this answer with code so I can an exact example of how to fix this? https://stackoverflow.com/a/49350647/627473 – Chris Muench Sep 20 '19 at 22:51
  • @ChrisMuench can you explain more about what exactly do you need to achieve? Some minimal code would be welcomed too. (And a comment on the question, so we can mention you there) – Mojtaba Hosseini Sep 21 '19 at 12:49
  • I am looking for code that would allow a WKWebView to run JavaScript when covered by another view – Chris Muench Sep 21 '19 at 14:32
  • I tried this but I don’t know where to put this code. Also is this a new empty wkwebview or should this be added to my existing view which is created in Ui builder – Chris Muench Sep 21 '19 at 17:55
  • You could add that approach into your code. But I cannot help you more without seeing any code. But you can check this link and maybe it will help you. https://stackoverflow.com/questions/32582198/load-local-javascript-in-webview – Ömürcan Cengiz Sep 21 '19 at 21:43
  • All I have is a WKWebView in Interface Builder with an outlet in view controller. I am trying to make this WKWebView run code even when covered – Chris Muench Sep 26 '19 at 15:01
  • I get it, but like I said before, I can't help you more any further without see a little code. This link may help you. https://www.hackingwithswift.com/articles/112/the-ultimate-guide-to-wkwebview – Ömürcan Cengiz Sep 26 '19 at 18:03
  • There isn’t any. It is just a web view. Are you looking for code the executes JavaScript? – Chris Muench Sep 26 '19 at 21:25