KINWebBrowser是一个用于 iOS 应用程序的开源 Web 浏览器模块。我最近升级了 KINWebBrowser 以使用WKWebView开始逐步淘汰 UIWebView。这产生了显着的改进,但是:
问题:WKWebView 不允许用户启动包含电话号码、电子邮件地址、地图等 URL 的链接。
当从显示的页面作为链接启动时,如何配置 WKWebView 以启动这些备用 URL 的标准 iOS 行为?
关于WKWebKit的更多信息
KINWebBrowser是一个用于 iOS 应用程序的开源 Web 浏览器模块。我最近升级了 KINWebBrowser 以使用WKWebView开始逐步淘汰 UIWebView。这产生了显着的改进,但是:
问题:WKWebView 不允许用户启动包含电话号码、电子邮件地址、地图等 URL 的链接。
当从显示的页面作为链接启动时,如何配置 WKWebView 以启动这些备用 URL 的标准 iOS 行为?
关于WKWebKit的更多信息
通过将此功能添加到您的 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);
}
适用于 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)
}
}
您需要实现另一个回调才能做到这一点(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() 方法。
这对 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"
。
斯威夫特 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
我来到这里寻找如何在 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)
}
上面的答案对我有用,但我需要它来重写 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
}
}
}