2010-03-28 13 views
40

Tengo un UIWebView incrustado en una aplicación de iPhone mía. Deseo poder tener ciertos enlaces dentro de esa vista web abiertos a la aplicación Mobile Safari completa (es decir, no a mi versión incrustada).Forzar un enlace WebView para iniciar Safari?

¿Hay alguna manera simple de estructurar algunos de mis hrefs para forzar esto, en lugar de abrir cada enlace dentro de mi vista web incrustada?

Gracias.

+0

[http://stackoverflow.com/questions/4452719/cómo-do-i-abierto-links-en-Safari-lugar-de-UIWebView/12103579 # 12103579] [1] [1]: http: // stackoverflow.com/questions/4452719/how-do-i-open-links-in-safari-instead-of-uiwebview/12103579 # 12103579 –

Respuesta

12

No he probado esto por mí mismo, pero creo que se puede implementar el método UIWebViewDelegate

webView:shouldStartLoadWithRequest:navigationType 

que será llamado cada vez que un eslabón de la UIWebView se hace clic en. En ese método, solo necesita determinar si el enlace hecho clic debería dar como resultado el inicio de Safari o no, y usar openURL si fuera necesario.

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { 

    // Check if this was a click event and then some other criteria for determining if you want to launch Safari. 
    if (navigationType == UIWebViewNavigationTypeLinkClicked && [Some other criteria]) { 
     [[UIApplication sharedApplication] openURL:request.URL]; 

     // Return false to indicate to the UIWebView to not navigate to the linked target 
     return false; 
    } 

    // Return true so that the UIWebView loads the link target 
    return true; 
} 

No olvide que es necesario establecer su propiedad UIWebView delegado a una instancia de la clase que implementa la UIWebViewDelegate.

61

Para ampliar lo que dijo Randy, esto es lo que yo uso en mi solicitud para que cada http: //, https: //, y mailto: // URL abierta en las aplicaciones Safari o Mail externos:

-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType; 
{ 
    NSURL *requestURL =[ [ request URL ] retain ]; 
    if (([ [ requestURL scheme ] isEqualToString: @"http" ] || [ [ requestURL scheme ] isEqualToString: @"https" ] || [ [ requestURL scheme ] isEqualToString: @"mailto" ]) 
     && (navigationType == UIWebViewNavigationTypeLinkClicked)) { 
     return ![ [ UIApplication sharedApplication ] openURL: [ requestURL autorelease ] ]; 
    } 
    [ requestURL release ]; 
    return YES; 
} 

Como dice Randy, querrá implementar esto en cualquier clase que configure para ser el delegado de UIWebView. Para que solo las URL seleccionadas inicien Safari, puede cambiar su esquema de http: // a safari: //, o algo similar, y solo cancelar esas URL en el sistema (después de reemplazar el esquema de URL personalizado con http: //) .

Lo hago en mi documentación interna de ayuda, que es el HTML que se muestra en un UIWebView, para que no tenga problemas en el proceso de revisión con un navegador web de propósito general incrustado en mi aplicación.

+0

¿No está reteniendo y liberando la URL realmente paranoica? – morningstar

+0

@morningstar - Tal vez, y ahora está obsoleto con ARC, pero en ese momento estaba luchando con bloqueos relacionados con subprocesos en otros lugares (objetos liberados automáticamente que se pasaron a métodos en diferentes hilos que se desasignan en medio de ese método), así que me equivoqué del lado de ser paranoico. Nuevamente, ARC lo hace ahora por usted, así que mi código ya no tiene esto en él. –

+0

Sí, está bien, puedo ver cómo podría ser necesario debido a problemas de subprocesos. – morningstar

20

Ok, lo tengo. Tal vez no es la solución perfecta, pero se puede hacer así:

Sólo en su WebViewController.m:

añada la línea webView.delegate = self; al procedimiento viewDidLoad:

- (void)viewDidLoad { 
    webView.delegate = self; 
    .... your code .... 
} 

continuación, puede añadir como se describió anteriormente en alguna parte en el Controller.m Archivo siguiente función booleana resultante:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { 
    if (navigationType == UIWebViewNavigationTypeLinkClicked) { 
     [[UIApplication sharedApplication] openURL:request.URL]; 
     return false; 
    } 
    return true; 
} 
+1

Para newbs, establecer el bit sobre el delegado es importante :) – firecall

+0

Thanku much :) –

1

Esta es la forma en que lo resolvimos, añadir esto a su archivo ViewController.m:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 
    first.delegate = (id)self; 
       [first loadRequest:[NSURLRequest requestWithURL:[NSURL  URLWithString:@"http://my.FellowshipNWA.org?publicapp"]]]; 
} 

// Add section below so that external links & PDFs will open in Safari.app 
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request  navigationType:(UIWebViewNavigationType)navigationType { 
    if (navigationType == UIWebViewNavigationTypeOther) { 
     NSString *checkURL = @"http://my.fellowshipnwa.org/?givenowsafari"; 
     NSString *reqURL = request.URL.absoluteString; 
     if ([reqURL isEqualToString:checkURL]) 
      { 
       [[UIApplication sharedApplication] openURL:request.URL]; 
      return false; 
    } 
     else { 
      return true; 
     } 
    } 
    return true; 
} 
1

versión Swift de la respuesta de Brad Larson:

func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool { 

    var url: NSURL = request.URL! 
    var isExternalLink: Bool = url.scheme == "http" || url.scheme == "https" || url.scheme == "mailto" 
    if (isExternalLink && navigationType == UIWebViewNavigationType.LinkClicked) { 
     return !UIApplication.sharedApplication().openURL(request.URL!) 
    } else { 
     return true 
    } 
} 
Cuestiones relacionadas