Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining when stringByEvaluatingJavaScriptFromString has finished

I have a UIWebView which loads up an HTML page. This page has two buttons on it, say Exit and Submit. I don't want users to be able to click the Exit button, so once the page has finished loading (ie. webViewDidFinishLoad is called), I use stringByEvaluatingJavaScriptFromString to remove one of these buttons, by manipulating the HTML. I also disable user interaction on the UIWebView on webViewDidStartLoad, and enable it again on webViewDidFinishLoad.

The problem I am finding is that stringByEvaluatingJavaScriptFromString takes a second or two to complete, and it seems to be done in it's own thread. So what is happening is that webViewDidFinishLoad is called, user interaction is enabled on the UIWebView, and if the user is quick, they can click the Exit button before stringByEvaluatingJavaScriptFromString has finished. As stringByEvaluatingJavaScriptFromString seems to be on it's own thread with no way to know when it's finished (it doesnt call webViewDidFinishLoad), the only way to completely prevent users from tapping the Exit button that I can see is to only enable user interaction on the UIWebView after some delay, which is unreliable (how can I really know how long to delay for?).

Am I correct in that stringByEvaluatingJavaScriptFromString is done on it's on thread, and I have no way of being able to tell when it's finished? Any other suggestions for how to get around this problem?

EDIT: In short, what I want to know is if it is possible to disable a UIWebView while stringByEvaluatingJavaScriptFromString is executing, and re-enable the UIWebView when the javascript is finished.

EDIT 2: There's an article here which seems to imply you can somehow poll the JS engine to see when it's finished, but I can't find any other references saying the same thing: http://drnicwilliams.com/2008/11/10/to-webkit-or-not-to-webkit-within-your-iphone-app/

EDIT 3 Based on the answer from Brad Smith, it seems that I actually need to know when the UIWebView has finished loading itself after the javascript has executed. It's looking more and more like I just need to put a delay of sorts in there.

like image 602
Ben Williams Avatar asked Jan 14 '11 07:01

Ben Williams


4 Answers

You could have the javascript you are injecting into the page, attempt to navigate the page elsewhere (document.location="foo"), and use webView:ShouldLoadRequest: to look for that request and return no as well as trigger what you need to (and normally returning yes).

like image 151
Brad The App Guy Avatar answered Nov 12 '22 17:11

Brad The App Guy


stringByEvaluatingJavascriptFromString has to be done when it returns. It may be done on a different thread (probably not since it can change the UI), but the method cannot return the string result until it has a result to return.

like image 31
ughoavgfhw Avatar answered Nov 12 '22 16:11

ughoavgfhw


After executing stringByEvaluatingJavascriptFromString, you can try below code to solve your problem

webView.userInteractionEnabled = NO;
while (webView.loading) {
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.2]];
}
webView.userInteractionEnabled = YES;

Let me know its working for you or not.

like image 20
Paras Gandhi Avatar answered Nov 12 '22 16:11

Paras Gandhi


How about inlining a stub function for the onclick event directly on the html element. You could bind the html element to an onclick event handler function later when it's more appropriate.

<button onclick="function () { };"/>
like image 26
dot slash hack Avatar answered Nov 12 '22 15:11

dot slash hack