4
votes

I'm working on an iPad app which is based on a UIWebView: to explain it in the simplest possible terms, the app shows one big interactive webview and in addition it supports custom gestures.

I need to catch events that represent single taps on the webview, but only when the taps have not already been consumed by the webview (i.e. they are not the beginning of a scroll/zoom operation, they are not taps on links, they are not taps that trigger some javascript).

The UIWebView is very greedy with its events, and in my experience it tends not to propagate them, even when they are not consumed. To catch the events, I ended up subclassing the main UIWindow (see http://mithin.in/2009/08/26/detecting-taps-and-events-on-uiwebview-the-right-way/). This is working well, but the problem is I'm not able to recognize whether the taps I'm getting have triggered some javascript in the webview or not.

As an additional restriction, I have no control over the javascript that's going to run in the UIWebView or the HTML that it's going to be displayed.

So, the question goes like this: what would be a way to detect all and only the tap events which did not trigger any other action in the UIWebView itself, especially javascript actions?

~

Should you be curious, the source code of the project I'm working on is on GitHub: to find it, just ask Google to point you to Baker Framework.

1

1 Answers

4
votes

Do this with JavaScript. First, after your webview finishes loading, attach a javascript click handler to the body to soak up any unused clicks. Have it load a made-up domain as it's action:

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    NSString *script = @"document.body.onclick = function () { document.location.href = 'http://clickhandler'; }"
    [webView stringByEvaluatingJavaScriptFromString:script];
}

Then in your webview delegate, look out for attempts to load that made up domain and intercept them. You now have a way to intercept that javascript click handler with native code and react accordingly:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    if ([request.URL.host isEqualToString:@"clickhandler"])
    {
        //handle click
        //your logic here
        return NO;
    }
    return YES;
}