3

I am successfuly using an invisible UIWebView as an execution engine for Javascript snippets. Contrary to what certain pages suggest, it does not require to be visible. If declared dead simply as

UIWebView* myJSExecutor = [UIWebView new];

not only it executes any stringByEvaluatingJavaScriptFromString: thrown at it, it even bubbles alert() to the desktop! (Not that it's something you would like to do often) Disclaimer: tested only on iOS 5+

Now, I have another normally visible UIWebView with normal webpage content, and I want it to suspend JavaScript execution: that is stop acting on timer and DOM events. I thought that removeFromSuperview with stopLoading and setting delegate = nil would do the trick. But no, as soon as I add the UIWebView back to some visible view, I can see that the timers were running all the time.

I understand the schizophreny of my requirement. I appreciate it working in the background on one hand (contrary to some observations), but I want to suspend it on the other hand. But still I would like to ask if there is any, perhaps even private way to suspend it. Safari for iOS is capable of suspending browser tabs in the background. Chrome for iOS can't, which may be a sad negative proof :(

3 Answers 3

3
+100

If you're looking for crazy, I have an idea.

The only way I know to pause JavaScript is to show an alert, confirm, prompt, or sending an ajax request with async=false.

Is the alert hidden when the UIWebView is hidden? If so, you could send an alert when you want it to freeze. The user would have to dismiss it when you showed the view again:

[web stringByEvaluatingJavaScriptFromString:@"alert('Press OK to continue...')"];

Or maybe you could dismiss it programmatically. I'm sure you'd agree that this whole suggestion is bound for trouble, but it's a thought.

Sign up to request clarification or add additional context in comments.

2 Comments

"Is the alert hidden when the UIWebView is hidden?" Unfortunately NO. Alerts bubble up regardless of the visibility, or even having a (super)view context at all. As i wrote in the question. But sending ajax request with async=false made us thinking. +1. It's not a top priority for now, but i promise getting back to you if it works.
I'm giving you the bounty since this is the only suggestion that might work given our particular requirements (need for full UIWebView, no control over page contents). As @PavelZdenek says, the alert won't work, but we will try the synchronous XMLHttpRequest once we've gotten through the more urgent tasks in our work queue.
1

Do you need a full UIWebView? If not you could just invoke JavaScriptCore directly.

- (NSString *)runJS:(NSString *)aJSString 
{
    JSContextRef ctx = JSGlobalContextCreate(NULL); 
    JSStringRef scriptJS = JSStringCreateWithUTF8CString([aJSString UTF8String]);
    JSValueRef exception = NULL;
    JSValueRef result = JSEvaluateScript([self JSContext], scriptJS, NULL, NULL, 0, &exception); 
    JSGlobalContextRelease(ctx);
    ...

This would give you more control over the entire JS runtime, but unfortunately I've not found an API to suspend execution of timers other than releasing the whole context.

For a more complete example of how to use JavaScriptCore see https://github.com/jfahrenkrug/AddressBookSpy/blob/master/AddressBookSpy/AddressBookSpy/ABSEngine.m

1 Comment

Unfortunately i need a full UIWebView, yes. +1 for the JavaScriptCore hint.
1

This might sound obvious, but if you can edit the JS you're running in the UIWebView, can't you just store a global variable in the JS called 'paused', and check that when your timers are firing?

var paused = false;
var thread = setInterval(function() {
    if(!paused) {
         // normal timer checking etc
    }
}, 300);

Then just fire [webView stringByEvaluatingJavaScriptFromString:@"paused = true;"] when you remove the webview, and set paused = false when you add it back to the view.

1 Comment

Unfortunately i don't control the page content. It's a web browser, hence its author may be doing whatever he pleases with the timers. But yes, you confirm one of our "dead end" theories :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.