plugin engine ios ios4 uiwebview ios5

ios - cordova-plugin-wkwebview-engine



Abrir target=enlaces “_ en blanco” fuera de UIWebView en Safari (5)

Basé mi respuesta en la de Benjamin Piette, pero necesitaba ajustar la secuencia de comandos, ya que los enlaces que se ajustarán en mi caso fueron generados de forma asíncrona por otro javascript.

NSString* const kOpenInNewTabPrefix = @"myOpenInNewTabPrefix:";//This NEEDS to end with '':'' - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { if ([[request.URL.absoluteString lowercaseString] hasPrefix:[kOpenInNewTabPrefix lowercaseString]]) { // JS-hacked URl is a target=_blank url - manually open the browser. NSURL *url = [NSURL URLWithString:[request.URL.absoluteString substringFromIndex:[kOpenInNewTabPrefix length]]]; [[UIApplication sharedApplication] openURL:url]; return YES; } return YES; } - (void)webViewDidFinishLoad:(UIWebView *)webView { //based on http://stackoverflow.com/questions/8490038/open-target-blank-links-outside-of-uiwebview-in-safari // JS Injection hack to solve the target="_blank" issue and open a real browser in such case. NSString *JSInjection = [NSString stringWithFormat:@"javascript: " "document.getElementsByTagName(''body'')[0].addEventListener(''click'', function(e){" " var a = e.target;" " if(a.nodeName != ''A''){" " return;" " }" " var target = a.target;" " var href = a.href;" " var prefix = ''%@'';" " if(href.substring(0, %lu) != ''%@'' && target == ''_blank''){" " a.href = prefix + href;" " }" "})" , [kOpenInNewTabPrefix lowercaseString] , (unsigned long)[kOpenInNewTabPrefix length] , [kOpenInNewTabPrefix lowercaseString]]; [webView stringByEvaluatingJavaScriptFromString:JSInjection]; }

Dentro de mi aplicación iOS tengo un UIWebView.

Ahora quiero que todos los enlaces que tienen el atributo target = "_ blank" no se abran dentro de mi WebView sino externamente en Safari.

¿Cómo puedo hacer esto?


El problema con la solución de wedo es que todos sus enlaces se abrirán en Safari.

Dos soluciones:

1: devolución de llamada de JavaScript a Objective-C cuando target = "_ blank"
Para resolver su problema, debe agregar un poco de javascript en todos sus enlaces, verifique si tienen el atributo _blank, luego vuelva a llamar su código objetivo-C desde JavaScript y ejecute:

[[UIApplication sharedApplication] openURL:myUrl];

Personalmente no me gusta esta solución porque es un montón de código, devolución de llamada, complejidad y un poco complicado ...

2 - Comprobando el parámetro url
Si tiene acceso al código HTML (tenga en cuenta que en ambas soluciones necesita acceso a HTML) le recomiendo eliminar el target = "_ blank" y agregar el parámetro? OpenInSafari = true

En el UIWebViewDelegate agregue el siguiente código:

-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { if (navigationType == UIWebViewNavigationTypeLinkClicked) { NSURL *url = [request URL]; NSDictionary *param = [url queryParameters]; NSString *openIsSafari = [param objectForKey:@"openInSafari"]; if ( openIsSafari!= nil && ([openIsSafari isEqualToString:@"true"] || [openIsSafari isEqualToString:@"1"])){ [[UIApplication sharedApplication] openURL:url]; return NO; } } return YES; }

Un buen (¿mal?) Punto con esta solución es que si los niveles de enlace x más profundos aún pueden abrir enlaces en el navegador de safari

<a href="http://www.google.com?openInSafari=true">Google in Safari</a>


Siempre agregue el protocolo en la URL (http, https ...)


Felicitaciones a Martin Magakian! Aquí está la modificación basada en la sugerencia de spankmaster79:

- (BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest: (NSURLRequest *)request navigationType: (UIWebViewNavigationType)navigationType { if (navigationType == UIWebViewNavigationTypeLinkClicked) { NSURL *url = [request URL]; NSString *param = [url query]; if ([param rangeOfString: @"openInSafari=true"].location != NSNotFound){ [[UIApplication sharedApplication] openURL: url]; return NO; } } return YES; }


Mi respuesta, que es una respuesta que encontré en el desbordamiento de pila para Android WebView. Pero en realidad, ambas webview tienen el mismo problema y la misma solución (sucia):

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { if ([request.URL.absoluteString hasPrefix:@"newtab:"]) { // JS-hacked URl is a target=_blank url - manually open the browser. NSURL *url = [NSURL URLWithString:[request.URL.absoluteString substringFromIndex:7]]; [[UIApplication sharedApplication] openURL:url]; return true; } return true; } - (void)webViewDidFinishLoad:(UIWebView *)webView { // JS Injection hack to solve the target="_blank" issue and open a real browser in such case. NSString *JSInjection = @"javascript: var allLinks = document.getElementsByTagName(''a''); if (allLinks) {var i;for (i=0; i<allLinks.length; i++) {var link = allLinks[i];var target = link.getAttribute(''target''); if (target && target == ''_blank'') {link.setAttribute(''target'',''_self'');link.href = ''newtab:''+link.href;}}}"; [webView stringByEvaluatingJavaScriptFromString:JSInjection]; }

Esto resuelve el problema target = "_ blank" para abrir en safari, Y sigue abriendo enlaces estándar dentro de la vista web.


Tenía la misma pregunta y, desafortunadamente, estas respuestas me atrajeron de una manera completamente equivocada y muy compleja. Realmente, la pregunta se responde tan simplemente como "necesita usar WebViewPolicyDelegateProtocol".

En -viewVidLoad de la implementación del controlador de vista escribe:

[myWebView setPolicyDelegate:self];

En su interfaz de clase de controlador de vista debe agregar dos elementos:

- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener; - (void)webView:(WebView *)webView decidePolicyForNewWindowAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request newFrameName:(NSString *)frameName decisionListener:(id<WebPolicyDecisionListener>)listener;

Y ponerlos en práctica tan fácil como:

- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener { // just the default behavior, though you''re free to add any url filtering you like... [listener use]; } - (void)webView:(WebView *)webView decidePolicyForNewWindowAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request newFrameName:(NSString *)frameName decisionListener:(id<WebPolicyDecisionListener>)listener { // frameName is your "target" parameter value if([frameName isEqualToString:@"_blank"]) { [[NSWorkSpace sharedWorkSpace] loadURL:[request URL]]; } else { [listener use]; } }

Consulte también la documentación de Apple.

He usado de esta manera en mi proyecto, donde el conjunto de marcos se usa en el HTML raíz, cargado en la vista web. Todos los enlaces cruzados que apuntan a otro marco existente no causan la segunda llamada de mensaje, por lo que aquí solo se procesan nuevos destinos (externos). Funciona bien para mí.