ios - raywenderlich - wkwebview nscoding support was broken
Lanzamiento de enlaces de teléfono/correo electrónico/mapa en WKWebView (7)
KINWebBrowser es un módulo de navegador web de código abierto para aplicaciones iOS. Recientemente actualicé KINWebBrowser para usar WKWebView para comenzar a eliminar UIWebView. Esto produce mejoras significativas, pero:
Problema: WKWebView no permite a los usuarios lanzar enlaces que contengan direcciones URL para números de teléfono, direcciones de correo electrónico, mapas, etc.
¿Cómo puedo configurar un WKWebView para iniciar los comportamientos estándar de iOS para estas URL alternativas cuando se inician como enlaces desde la página mostrada?
Todo el KINWebBrowser
Más información en WKWebKit
Esto me ayuda para 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
}
EDITADO:
En el enlace debe ser el atributo target="_blank"
.
Funciona en xcode 8.1, Swift 2.3.
Para target = "_ blank", número de teléfono (tel :) y correo electrónico (mailto :) enlaces.
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)
}
}
Actualizado para 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)
}
}
La respuesta anterior funciona para mí, pero la necesitaba para volver a escribir para 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
}
}
}
Llegué aquí buscando cómo abrir archivos adjuntos de gmail en wkwebview.
Mi solución es simple:
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)
}
Necesita implementar otra devolución de llamada para obtener este derecho (Swift 3.1):
// 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.startsWith("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.startsWith("mailto:"):
if UIApplication.shared.canOpenURL(failingUrl) {
UIApplication.shared.openURL(failingUrl)
return
}
// Needed to open Appstore-App
case _ where failingUrlStr.startsWith("itmss://itunes.apple.com/"):
if UIApplication.shared.canOpenURL(failingUrl) {
UIApplication.shared.openURL(failingUrl)
return
}
default: break
}
}
Ahora se llama a Facebook, Mail, Appstore, .. directamente desde su aplicación sin la necesidad de abrir Safari
Pude hacerlo funcionar para el enlace de Google Maps (que parece estar relacionado con el target = "_ blank") y para el esquema tel: agregando esta función a su KINWebBrowserViewController.m
- (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);
}
ACTUALIZACIÓN PARA SWIFT 4.2
Lamento desenterrar una publicación anterior, pero tenía los mismos problemas y he actualizado la solución para Swift 4.2. He puesto mi solución aquí para que pueda ayudar a otros y, si no, espero que la encuentre la próxima vez que trabaje con 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)
}
}
Utilicé el siguiente sitio como inspiración:
SubzDesignz iOS Swift 4 WKWebview - Detecte tel, mailto, target = "_ blank" y CheckConnection