拦截UIWebView中未使用的点击事件

4
我正在开发一个基于UIWebView的iPad应用程序:简单来说,该应用程序显示一个大型交互式Web视图,并支持自定义手势。
我需要捕获代表Web视图上的单击事件,但仅当这些单击事件尚未被Web视图消耗时(即它们不是滚动/缩放操作的开始,它们不是链接上的单击,它们不是触发某些JavaScript的单击)。
UIWebView对其事件非常贪婪,在我的经验中,即使它们没有被消耗,它也倾向于不传播它们。为了捕获事件,我最终子类化了主窗口(请参见http://mithin.in/2009/08/26/detecting-taps-and-events-on-uiwebview-the-right-way/)。这个方法很有效,但问题是我无法识别我获取的单击是否已在Web视图中触发了一些JavaScript。
作为附加限制,我无法控制将在UIWebView中运行的JavaScript或将要显示的HTML。

所以,问题是这样的:有什么方法可以检测到所有且仅有在UIWebView中没有触发任何其他操作,特别是JavaScript操作的轻击事件?

~

如果您感兴趣,我正在开发的项目源代码在GitHub上:要找到它,只需让Google指向Baker Framework。

1个回答

4

使用JavaScript实现。首先,在您的Web视图完成加载后,将JavaScript点击处理程序附加到主体以吸收任何未使用的点击。将其作为操作加载为虚构域:

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

然后在您的 webview 委托中,注意检测试图加载那个虚构的域名并拦截它们。现在您有一种通过本地代码拦截该 javascript 点击处理程序并做出反应的方法:

- (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;
}

2
+1 但是,与其使用虚假主机,我通常建议使用自定义方案。因此,不要使用 http://clickhandler,而是使用 handler:,并使用 request.URL.scheme 进行检查。这样可以轻松传递数据,例如 handle:click,并且比虚假主机更明确。 - Rob Napier
我最初也是这么想的,但这不是一个好主意。除非将自定义方案添加到您的info.plist中作为受支持的方案,否则自定义方案将无法工作。如果任何人在Safari中键入该方案,它将启动您的应用程序,这是一个不希望发生的副作用,因为该方案应该是您的应用程序的内部协议。使用带有虚假主机的http://(即结尾没有.com)是安全的,因为它不可能与真实域名冲突。 - Nick Lockwood
我经常这样做。您不需要注册自定义方案才能在Web视图委托中捕获它。只有当您希望其他应用程序将其转发给您时,才需要注册它。 - Rob Napier
我非常确定,除非应用程序正确声明了自定义方案,否则Webviews以前无法正确处理它们,但也许现在不再是这种情况。 - Nick Lockwood
试一下。就像我说的那样,我已经用这种方法很长时间了,而我的当前项目也严重依赖它。这里有一篇博客文章详细介绍了它:http://www.icab.de/blog/2009/08/05/webkit-on-the-iphone-part-2/ - Rob Napier
你是正确的 - 它可以使用自定义方案运作,而那是更好的解决方案。 - Nick Lockwood

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接