Tengo un UIWebView muy simple con contenido de mi paquete de aplicaciones. Me gustaría que cualquier enlace en la vista web se abra en Safari en lugar de en la vista web. es posible?
Tengo un UIWebView muy simple con contenido de mi paquete de aplicaciones. Me gustaría que cualquier enlace en la vista web se abra en Safari en lugar de en la vista web. es posible?
Respuestas:
Agregue esto al delegado UIWebView:
(editado para verificar el tipo de navegación. también puede pasar file://
solicitudes que serían enlaces relativos)
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked ) {
[[UIApplication sharedApplication] openURL:[request URL]];
return NO;
}
return YES;
}
Versión rápida:
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if navigationType == UIWebViewNavigationType.LinkClicked {
UIApplication.sharedApplication().openURL(request.URL!)
return false
}
return true
}
Versión Swift 3:
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if navigationType == UIWebViewNavigationType.linkClicked {
UIApplication.shared.openURL(request.url!)
return false
}
return true
}
Versión Swift 4:
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebView.NavigationType) -> Bool {
guard let url = request.url, navigationType == .linkClicked else { return true }
UIApplication.shared.open(url, options: [:], completionHandler: nil)
return false
}
Actualizar
Como openURL
ha quedado en desuso en iOS 10:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked ) {
UIApplication *application = [UIApplication sharedApplication];
[application openURL:[request URL] options:@{} completionHandler:nil];
return NO;
}
return YES;
}
switch
es preferible para los tipos de enumeración
Si alguien se pregunta, la solución de Drawnonward se vería así en Swift :
func webView(webView: UIWebView!, shouldStartLoadWithRequest request: NSURLRequest!, navigationType: UIWebViewNavigationType) -> Bool {
if navigationType == UIWebViewNavigationType.LinkClicked {
UIApplication.sharedApplication().openURL(request.URL)
return false
}
return true
}
UIWebViewDelegate
Un comentario rápido a la respuesta del usuario 306253: tenga cuidado con esto, cuando intente cargar algo en UIWebView (es decir, incluso desde el código), este método evitará que suceda.
Lo que puede hacer para evitar esto (gracias Wade) es:
if (inType == UIWebViewNavigationTypeLinkClicked) {
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
return YES;
También es posible que desee manejar los tipos UIWebViewNavigationTypeFormSubmitted
y UIWebViewNavigationTypeFormResubmitted
.
Las otras respuestas tienen un problema: se basan en la acción que realiza y no en el enlace en sí para decidir si cargarlo en Safari o en la vista web.
Ahora a veces esto es exactamente lo que quieres, lo cual está bien; pero en otras ocasiones, especialmente si tiene enlaces de anclaje en su página, realmente desea abrir solo enlaces externos en Safari, y no enlaces internos. En ese caso, debe verificar la URL.host
propiedad de su solicitud.
Utilizo ese fragmento de código para verificar si tengo un nombre de host en la URL que se está analizando o si está incrustado html:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
static NSString *regexp = @"^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9-]*[a-zA-Z0-9])[.])+([A-Za-z]|[A-Za-z][A-Za-z0-9-]*[A-Za-z0-9])$";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regexp];
if ([predicate evaluateWithObject:request.URL.host]) {
[[UIApplication sharedApplication] openURL:request.URL];
return NO;
} else {
return YES;
}
}
Por supuesto, puede adaptar la expresión regular a sus necesidades.
if (request.URL?.scheme != "file")
En Swift puedes usar el siguiente código:
extension YourViewController: UIWebViewDelegate {
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebView.NavigationType) -> Bool {
if let url = request.url, navigationType == UIWebView.NavigationType.linkClicked {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
return false
}
return true
}
}
Asegúrese de verificar el valor de URL y el tipo de navegación.
Aquí está el equivalente de Xamarin para iOS de la respuesta de drawnonward.
class WebviewDelegate : UIWebViewDelegate {
public override bool ShouldStartLoad (UIWebView webView, NSUrlRequest request, UIWebViewNavigationType navigationType) {
if (navigationType == UIWebViewNavigationType.LinkClicked) {
UIApplication.SharedApplication.OpenUrl (request.Url);
return false;
}
return true;
}
}
La respuesta aceptada no funciona.
Si su página carga URL a través de Javascript, navigationType
será UIWebViewNavigationTypeOther
. Que, desafortunadamente, también incluye cargas de páginas de fondo, como análisis.
Para detectar la navegación de la página, debe compararla [request URL]
con [request mainDocumentURL]
.
Esta solución funcionará en todos los casos:
- (BOOL)webView:(UIWebView *)view shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)type
{
if ([[request URL] isEqual:[request mainDocumentURL]])
{
[[UIApplication sharedApplication] openURL:[request URL]];
return NO;
}
else
{
return YES;
}
}
Nota de rechazo de la aplicación:
Finalmente UIWbView
está muerto y Apple ya no lo aceptará.
Apple comenzó a enviar correos electrónicos a todos los propietarios de aplicaciones que todavía usan UIWebView
:
Uso de API en desuso: Apple dejará de aceptar envíos de aplicaciones que usan UIWebView
API.
Apple se toma muy en serio la privacidad del usuario y es obvio que no permitirán una vista web insegura .
Entonces, elimine UIWebView de su aplicación lo antes posible. no use intentar usar UIWebView
en la nueva aplicación creada y prefiero usar WKWebView
si es posible
ITMS-90809: Uso de API obsoleto: Apple dejará de aceptar envíos de aplicaciones que usen API UIWebView. Consulte https://developer.apple.com/documentation/uikit/uiwebview para obtener más información.
Ejemplo:
import UIKit
import WebKit
class WebInfoController: UIViewController,WKNavigationDelegate {
var webView : WKWebView = {
var webview = WKWebView()
return webview
}()
var _fileName : String!
override func viewDidLoad() {
self.view.addSubview(webView)
webView.fillSuperview()
let url = Bundle.main.url(forResource: _fileName, withExtension: "html")!
webView.loadFileURL(url, allowingReadAccessTo: url)
let request = URLRequest(url: url)
webView.load(request)
}
func webView(webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: NSError) {
print(error.localizedDescription)
}
func webView(webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
print("Strat to load")
}
func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
print("finish to load")
}
}
En mi caso, quiero asegurarme de que absolutamente todo en la vista web abra Safari, excepto la carga inicial, así que uso ...
- (BOOL)webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if(inType != UIWebViewNavigationTypeOther) {
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
return YES;
}