Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WKWebview does not run javascript(XML HTTP request) with out adding a parent view

Tags:

wkwebview

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.

like image 613
Subba Avatar asked Oct 22 '14 18:10

Subba


2 Answers

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!

like image 81
mattr Avatar answered Nov 02 '22 01:11

mattr


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];
    }
}
like image 28
nabriski Avatar answered Nov 02 '22 01:11

nabriski