如何在UIWebView中可靠地检测链接点击?

时间:2013-01-16 12:44:10

标签: ios uiwebview

我有一个UIWebView,当用户点击链接时,我需要做一些事情。有一个委托回调,可用于检测水龙头:

- (BOOL) webView: (UIWebView*) webView
    shouldStartLoadWithRequest: (NSURLRequest*) request
    navigationType: (UIWebViewNavigationType) navigationType
{
    if (navigationType == UIWebViewNavigationTypeLinkClicked) {
        …
    }
}

问题是此代码无法处理所有链接点击。例如,一个普通的Google搜索结果页面会对链接产生一些奇怪的结果:

<a href="http://example.com/" class="l" onmousedown="return rwt(…)">
    <em>Link Text</em>
</a>

rwt功能会导致链接在点按时不会触发UIWebViewNavigationTypeLinkClicked事件。有没有办法可靠地检测落入“导航到其他页面”存储桶的所有事件?

4 个答案:

答案 0 :(得分:6)

到目前为止,我已经达成了以下解决方案。首先,我在加载时将一些JS代码注入页面:

function reportBackToObjectiveC(string)
{
    var iframe = document.createElement("iframe");
    iframe.setAttribute("src", "callback://" + string);
    document.documentElement.appendChild(iframe);
    iframe.parentNode.removeChild(iframe);
    iframe = null;
}

var links = document.getElementsByTagName("a");
for (var i=0; i<links.length; i++) {
    links[i].addEventListener("click", function() {
        reportBackToObjectiveC("link-clicked");
    }, true);
}

当用户点击链接时,由于webView:shouldStartLoadWithRequest: navigationType:委托致电,我提前知道:

if ([[[request URL] scheme] isEqualToString:@"callback"]) {
    [self setNavigationLeavingCurrentPage:YES];
    return NO;
}

然后,如果另一个请求到来且_navigationLeavingCurrentPage为真,我知道即使导航类型标志为UIWebViewNavigationTypeOther,用户也点击了链接。我仍然需要广泛地测试解决方案,因为我担心它会导致一些误报。

答案 1 :(得分:1)

我相信这可以通过在网站的HTML代码中嵌入一个监控事件的自定义JavaScript来实现,并根据您要监控的事件,它可以触发带有自定义URL方案的页面重定向,你可以在shouldStartLoadWithRequest中拦截它。

这样的事情:

<script>
// Function to capture events
function captureEvent(el) {
  window.location.href="callback://"+el.href;  
}

var elms = document.getElementsByTagName("a"); 
for (var i=0; i<elms.length; i++) {
  elms[i].addEventListener("onmousedown", function(){captureEvent(el)}, true); 

 }
</script>

然后在shouldStartLoadWithRequest中,您可以搜索具有callback:// url方案的NSURLRequest,并执行您想要的任何操作。

这尚未经过测试,但这样的事情可能会让你朝着正确的方向前进。

此外,由于提到了这一点,是的,您可以使用以下内容将自定义脚本添加到任何网页:

- (void)webViewDidFinishLoad:(UIWebView *)webView 
{
    [super webViewDidFinishLoad:webView];    
    [webView stringByEvaluatingJavaScriptFromString:@"document.body.insertAdjacentHTML('BeforeEnd','<script>....</script>');"];
}

答案 2 :(得分:1)

您需要添加此行

  

webView.dataDetectorTypes = UIDataDetectorTypeAll;

然后

  
      
  • (BOOL)webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType
  •   

方法会接到电话。

答案 3 :(得分:0)

我遇到了很多问题。使用UITapGestureRecognizer工作,除了它总是会收到点击,即使是链接。不幸的是,链接在被识别之前有大约300毫秒的延迟,这意味着手势识别器在识别链接之前获得了点击,这会产生时间问题(更糟糕的是因为你不应该硬编码时间等待以防万一Apple改变它)。此外,等待300毫秒以上的点击会给我的应用带来糟糕的用户体验。

所以我最终做的是将一个透明的div叠加在获得非链接点击的所有内容之上。然后,将链接放在更高的z级别。最后,确保所有内容都使用ontouchend="javascript:window.location.href='...';"。 ontouchend只会按照用户期望的点击发布。设置window.location.href加载一个新页面,确保所有点击调用-webView:shouldStartLoadWithRequest:navigationType:,我可以检查URL以查看我需要做什么。

HTML看起来像:     ...          ...     ...     ...

(我不完全确定“位置:亲戚”是否总是将事物置于同一位置,但它对我的简单页面效果很好;您的里程可能会有所不同。但是,您需要的位置:有序的东西让z-index起作用。)