22

KINWebBrowser是一个用于 iOS 应用程序的开源 Web 浏览器模块。我最近升级了 KINWebBrowser 以使用WKWebView开始逐步淘汰 UIWebView。这产生了显着的改进,但是:

问题:WKWebView 不允许用户启动包含电话号码、电子邮件地址、地图等 URL 的链接。

当从显示的页面作为链接启动时,如何配置 WKWebView 以启动这些备用 URL 的标准 iOS 行为?

所有代码都可以在这里找到

关于WKWebKit的更多信息

在此处查看KINWebBrowser GitHub 上的问题

4

7 回答 7

27

通过将此功能添加到您的 KINWebBrowserViewController.m,我能够使其适用于 Google 地图链接(似乎与 target="_blank" 相关)和电话:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    if(webView != self.wkWebView) {
        decisionHandler(WKNavigationActionPolicyAllow);
        return;
    }

    UIApplication *app = [UIApplication sharedApplication];
    NSURL         *url = navigationAction.request.URL;

    if (!navigationAction.targetFrame) {
        if ([app canOpenURL:url]) {
            [app openURL:url];
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }
    }
    if ([url.scheme isEqualToString:@"tel"])
    {
        if ([app canOpenURL:url])
        {
            [app openURL:url];
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}
于 2014-10-22T19:13:09.100 回答
11

适用于 xcode 8.1、Swift 2.3。

对于 target="_blank",电话号码 (tel:) 和电子邮件 (mailto:) 链接。

func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
    if webView != self.webview {
        decisionHandler(.Allow)
        return
    }

    let app = UIApplication.sharedApplication()
    if let url = navigationAction.request.URL {
        // Handle target="_blank"
        if navigationAction.targetFrame == nil {
            if app.canOpenURL(url) {
                app.openURL(url)
                decisionHandler(.Cancel)
                return
            }
        }

        // Handle phone and email links
        if url.scheme == "tel" || url.scheme == "mailto" {
            if app.canOpenURL(url) {
                app.openURL(url)
                decisionHandler(.Cancel)
                return
            }
        }

        decisionHandler(.Allow)
    }
}

为 swift 4.0 更新

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {

    if webView != self.webView {
        decisionHandler(.allow)
        return
    }

    let app = UIApplication.shared
    if let url = navigationAction.request.url {
        // Handle target="_blank"
        if navigationAction.targetFrame == nil {
            if app.canOpenURL(url) {
                app.open(url)
                decisionHandler(.cancel)
                return
            }
        }

        // Handle phone and email links
        if url.scheme == "tel" || url.scheme == "mailto" {
            if app.canOpenURL(url) {
                app.open(url)
            }

            decisionHandler(.cancel)
            return
        }

        decisionHandler(.allow)
    }

}
于 2016-11-22T13:02:05.843 回答
9

您需要实现另一个回调才能做到这一点(Swift 5.0):

// Gets called if webView cant handle URL
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
  guard let failingUrlStr = (error as NSError).userInfo["NSErrorFailingURLStringKey"] as? String  else { return }
  let failingUrl = URL(string: failingUrlStr)!

  switch failingUrl {
    // Needed to open Facebook
    case _ where failingUrlStr.hasPrefix("fb:"):
    if #available(iOS 10.0, *) {
       UIApplication.shared.open(failingUrl, options: [:], completionHandler: nil)
       return
    } // Else: Do nothing, iOS 9 and earlier will handle this

  // Needed to open Mail-app
  case _ where failingUrlStr.hasPrefix("mailto:"):
    if UIApplication.shared.canOpenURL(failingUrl) {
      UIApplication.shared.open(failingUrl, options: [:], completionHandler: nil)
      return
    }

  // Needed to open Appstore-App
  case _ where failingUrlStr.hasPrefix("itmss://itunes.apple.com/"):
    if UIApplication.shared.canOpenURL(failingUrl) {
      UIApplication.shared.open(failingUrl, options: [:], completionHandler: nil)
      return
    }

  default: break
  }
}

现在 Facebook、Mail、Appstore 等可以直接从您的应用程序调用,而无需打开 Safari

编辑:用标准的 hasPrefix() 方法替换了自定义的 startsWith() 方法。

于 2017-03-28T09:21:07.950 回答
0

这对 Xcode 8 WKWebview 有帮助

func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
    if navigationAction.targetFrame == nil {
        let url = navigationAction.request.url
        if url?.description.range(of: "http://") != nil || url?.description.range(of: "https://") != nil || url?.description.range(of: "mailto:") != nil || url?.description.range(of: "tel:") != nil  {
            UIApplication.shared.openURL(url!)
        }
    }
    return nil
}

编辑:

在链接中必须是属性target="_blank"

于 2016-10-03T09:06:42.797 回答
0

斯威夫特 4.2 更新

很抱歉挖掘了一篇旧帖子,但我遇到了同样的问题,并更新了 Swift 4.2 的解决方案。我已将我的解决方案放在这里,以便它可以帮助其他人,如果没有,我希望下次我使用 WKWebView 时能找到它!

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {

    let url = navigationAction.request.url?.absoluteString
    let urlElements = url?.components(separatedBy: ":") ?? []

    switch urlElements[0] {

    case "tel":
        UIApplication.shared.openURL(navigationAction.request.url!)
        decisionHandler(.cancel)
    case "mailto":
        UIApplication.shared.openURL(navigationAction.request.url!)
        decisionHandler(.cancel)
    default:
        decisionHandler(.allow)
    }
}

我使用以下网站作为灵感:

SubzDesignz iOS Swift 4 WKWebview – 检测 tel、mailto、target=”_blank” 和 CheckConnection

于 2018-11-26T11:49:03.620 回答
0

我来到这里寻找如何在 wkwebview 上打开 gmail 附件。

我的解决方案很简单:

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    if navigationAction.targetFrame == nil, let redirect = navigationAction.request.url {
        if UIApplication.shared.canOpenURL(redirect) {
            self.webViewMail?.load(navigationAction.request)
            decisionHandler(.cancel)
            return
        }
    }
    decisionHandler(.allow)
}
于 2018-04-11T13:15:31.533 回答
-1

上面的答案对我有用,但我需要它来重写 swift 2.3

if navigationAction.targetFrame == nil {
    let url = navigationAction.request.mainDocumentURL
    if url?.description.rangeOfString("mailto:")?.startIndex != nil ||
        url?.description.rangeOfString("tel:")?.startIndex != nil
    {
        if #available(iOS 10, *) {
            UIApplication.sharedApplication().openURL(url!,options: [:], completionHandler: nil)
        } else {
            UIApplication.sharedApplication().openURL(url!)  // deprecated
        }
    }
}
于 2016-11-07T12:44:27.263 回答