15
votes

I am updating my project from UIWebView to WKWebView. In existing UIWebView approach where UIWebView does't have any parent until it runs javascript and once it has content, it adds a parent to the webview. Content renders fine using UIWebView. I am using the same approach for WKWebView, however WKWebview stuck at loading. Is there any way we can execute javascript on wkwebview without adding parent to the webview. Another interesting thing is it works on simulator not on device. Using localHTTPServer to serve the html, css and images.

Any Suggestions or Tips to solve the above issue.

2

2 Answers

16
votes

I have observed similar behavior in my app running socket.io in a headless WKWebView. In my case, the web socket would disconnect all the time and not reconnect.

It seems that since WKWebView runs javascript off-process that it will pause any javascript that is considered idle to save resources (<-IMO). Idle includes not having a parent or the app/device is inactive. So, yes, it seems like you are correct in that it needs a parent view in most cases. I was able to work around this using the following code:

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. And, yes, I also observed that in the simulator this is not an issue (javascript ALWAYS runs, regardless of parent or app state)

Hope this helps!

7
votes

The accepted solution worked for me some of the time. I tried something else which appears to work for me consistently:

self.keepWebViewActiveTimer = [NSTimer scheduledTimerWithTimeInterval:0.2
                                 target:self 
                                 selector:@selector(_keepWKWebViewActive:)
                                 userInfo:nil
                                 repeats:YES];

Where _keepWKWebViewActive is:

-(void) _keepWKWebViewActive:(NSTimer*) timer{
    if(self.webView) {
        [self.webView evaluateJavaScript:@"1+1" completionHandler:nil];
    }
}