WKWebView与tel:links有关

时间:2018-03-05 12:56:02

标签: ios swift wkwebview

我已经看了很多这个问题的答案,但它们现在似乎已经过时了,没有一个解决方案适合我,只是给出了很多错误。

我刚刚进入xcode和apps,并将一个本地html文件“index.html”加载到WKWebView中。这很好,加载很好,显示它应该,但我有一些tel:页面上的链接不起作用,我点击它们什么也没有。我正在使用fraework7作为我的html文件,并添加了“外部”类,它可以在safari中运行等。

更新:使用以下代码我可以点击一个链接,它会尝试调用,但后来会发出致命错误

import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate{

    @IBOutlet weak var webview: WKWebView!
    override func viewDidLoad() {
        webview.navigationDelegate = self
        super.viewDidLoad()
        let htmlpath = Bundle.main.path(forResource: "index", ofType: "html")
        let url = URL(fileURLWithPath: htmlpath!)
        let request = URLRequest(url: url)
        webview.load(request)
        webview.scrollView.bounces = false
        webview.configuration.dataDetectorTypes = .phoneNumber
        // Do any additional setup after loading the view, typically from a nib.
    }
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Swift.Void) {
        if navigationAction.request.url?.scheme == "tel" {
            UIApplication.shared.openURL(navigationAction.request.url!)
            decisionHandler(.cancel)
        }
        decisionHandler(.allow)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

和html看起来像:

          <tr>

            <td>Police / Fire / Ambulance</td>

            <td>Emergency Services</td>

            <td><a href = "tel:999" class = "external">999</a></td>

          </tr>

显然是较大表的一部分,但这是一个例子。

任何指针都会非常感激,因为我已经圈了好几年了。

4 个答案:

答案 0 :(得分:2)

管理最终找到解决方案:

is.na()

使用这个似乎拿起tel:链接很好,我在这里找到的答案以前没有else语句因此解决了一次多次创建错误的decisionHandler,else语句修复了,现在看来很好。

答案 1 :(得分:0)

只需将WKNavigationDelegatedataDetectorTypes用于WKWebView的配置,如下所示:

webView.navigationDelegate = self
webView.configuration.dataDetectorTypes = [.link, .phoneNumber]

extension PDFWebViewController: WKNavigationDelegate {

    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        if let requestUrl = navigationAction.request.url, requestUrl.scheme == "tel" {
            UIApplication.shared.open(requestUrl, options: [:], completionHandler: nil)
            decisionHandler(.cancel)

        } else {
            decisionHandler(.allow)
        }
    }

}

答案 2 :(得分:0)

WKWebView并非开箱即用地处理tel:个链接。 mailto:facetime:之类的其他链接也不会被处理。有关这些特殊链接的完整列表,请参见Apple's documentation

您应确定要处理的Apple特殊链接中的哪一个(请参阅上面的链接),并以类似于以下方式的方式覆盖导航处理程序:

webView.navigationDelegate = self

...

extension ViewController: WKNavigationDelegate {

  func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    guard let url = navigationAction.request.url else {
      decisionHandler(.allow)
      return
    }

    if ["tel", "sms", "facetime"].contains(url.scheme) && UIApplication.shared.canOpenURL(url) {
      UIApplication.shared.open(url, options: [:], completionHandler: nil)
      decisionHandler(.cancel)
    } else {
      decisionHandler(.allow)
    }
  }
}

我之所以能想到Apple最初不包括此链接的唯一原因是,当您尝试在Mobile Safari中启动这些链接之一时,它会向您显示如下对话框:

  

该网站已被禁止自动启动通话。
  [忽略] [允许通话]

因此,他们可能希望您希望在您的应用中实现类似的功能,而不仅仅是发起呼叫。

但是请注意,每种链接的行为都不同:

  • tel:对话框,其中显示带有呼叫/取消按钮的电话号码。
  • sms:启动“消息”应用。
  • mailto:启动邮件应用。

因此,如果您确实希望具有某种模式,允许用户在不想执行该动作的情况下取消该模式,则取决于您支持的动作,它可能已经具有类似的行为(例如tel: )。

答案 3 :(得分:0)

虽然建议的答案工作正常 - 我建议使用白名单方法而不是黑名单。我们知道 WKWebView 只能处理 http/https 链接,所以我们可以优雅地处理打开任何其他类型链接的错误。

func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
    self.handleNavigationError(error)
}

func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
    self.handleNavigationError(error)
}

private func handleNavigationError(_ error: Error) {
    if let failedUrl = (error as NSError).userInfo[NSURLErrorFailingURLErrorKey] as? URL, failedUrlScheme = failedUrl.scheme?.lowercased(), !["http", "https"].contains(failedUrlScheme) {
        UIApplication.shared.open(failedUrl, completionHandler: nil)
    } else {
        // handle other errors if needed
    }
}

在这种情况下,您将支持所有类型的外部应用链接,例如 tel:sms:faceTime:itms-services: 等。