在 WKWebView 中启动电话/电子邮件/地图链接
Posted
技术标签:
【中文标题】在 WKWebView 中启动电话/电子邮件/地图链接【英文标题】:Launching phone/email/map links in WKWebView 【发布时间】:2014-10-22 06:01:29 【问题描述】:KINWebBrowser 是一个用于 ios 应用的开源网络浏览器模块。我最近升级了 KINWebBrowser 以使用 WKWebView 开始逐步淘汰 UIWebView。这产生了显着的改进,但是:
问题:WKWebView 不允许用户启动包含电话号码、电子邮件地址、地图等 URL 的链接。
如何配置 WKWebView 以在从显示的页面作为链接启动时启动这些备用 URL 的标准 iOS 行为?
所有code is available here
更多信息WKWebKit
见issue on the KINWebBrowser GitHub here
【问题讨论】:
你做不到。如果此功能对您很重要,那将是目前坚持使用 UIWebView 的原因 - 并向 Apple 提交增强请求。 UIWebView 可以做很多事情而 WKWebView 做不到。 【参考方案1】:通过将此函数添加到您的 KINWebBrowserViewController.m 中,我能够使其适用于 Google 地图链接(似乎与 target="_blank" 相关)和 tel: 方案
- (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);
【讨论】:
这段代码有点冗长,不保证会调用decisionHandler
。
好点!谢谢。这是一个深夜,最后一分钟的补丁,来自 2 个不同的来源,旨在快速解决问题。虽然它确实有效,但不是最干净的,而且肯定存在没有调用 decisionHandler 的情况。我已经编辑了代码。谢谢!
这段代码绝对是在正确的道路上,但它引入了一个安全漏洞,可能允许不情愿地发起呼叫和 FaceTime 呼叫。在这里查看我的解释:github.com/dfmuir/KINWebBrowser/issues/10
这个解决方案对我公司的我们帮助很大。谢谢达伦。我们可以稍微修改它,也可以通过我们网页的链接打开应用商店,并通过点击我们网页中的链接打开电子邮件应用程序。干杯!
为避免@dfmuir 指出的安全漏洞问题,请将url 更改为“telprompt”而不是默认的“tel”。例如,如果原始自定义 URL 是“tel:(212)%20555-6666”,则等效的 telprompt 是“telprompt:(212)%20555-6666”。这样用户在拨打电话前会得到提示【参考方案2】:
适用于 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)
【讨论】:
不要忘记添加委托:WKUIDelegate 和 var webView = WKWebView() 到属性【参考方案3】:您需要实现另一个回调才能做到这一点(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() 方法。
【讨论】:
什么是startsWith? 同hasPrefix() 但是为什么tel方案加载失败?【参考方案4】:这对 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
已编辑:
in 链接必须是属性target="_blank"
。
【讨论】:
【参考方案5】:我来到这里搜索如何在 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)
【讨论】:
【参考方案6】:SWIFT 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 – Detect tel, mailto, target=”_blank” and CheckConnection
【讨论】:
【参考方案7】:以上答案对我有用,但我需要它为 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
【讨论】:
以上是关于在 WKWebView 中启动电话/电子邮件/地图链接的主要内容,如果未能解决你的问题,请参考以下文章
如何用一根手指而不是两根手指移动地图(在 WKWebView 内)