2010-11-28 9 views
57

Recientemente descubrí que mi UIWebView se estaba ahogando en los enlaces de ITMS. Específicamente, desde UIWebView en mi aplicación, si navego a un sitio como this one y hago clic en el enlace "Disponible en el App Store", UIWebView podría generar un error con "Error Domain = WebKitErrorDomain Code = 101 La URL no se puede mostrar "¿Cómo manejar las URL de la aplicación en un UIWebView?

Después de googlear un poco, me di cuenta de que necesitaba captar las solicitudes de enlaces de aplicaciones y tener iOS para manejarlas. Empecé mirando para ver si el esquema comienza con "itms" en -webView:shouldStartLoadWithRequest:navigationType:, pero me di cuenta de que podría haber otros tipos de enlaces de aplicaciones que el sistema puede manejar. Así que se me ocurrió esto, en lugar:

- (void)webView:(UIWebView *)wv didFailLoadWithError:(NSError *)error { 
    // Give iOS a chance to open it. 
    NSURL *url = [NSURL URLWithString:[error.userInfo objectForKey:@"NSErrorFailingURLStringKey"]]; 
    if ([error.domain isEqual:@"WebKitErrorDomain"] 
     && error.code == 101 
     && [[UIApplication sharedApplication]canOpenURL:url]) 
    { 
     [[UIApplication sharedApplication]openURL:url]; 
     return; 
    } 

    // Normal error handling… 
} 

Tengo dos preguntas sobre este:

  1. Es ésta su sano juicio? Estoy comprobando específicamente el dominio de error y el código de error, y obtengo la cadena de URL de userInfo. ¿Es probable que eso permanezca?
  2. Esto funciona para el enlace de tienda de aplicaciones anteriormente vinculado, pero cuando vuelvo a mi aplicación, parece haber habido una solicitud fallida posterior que falló con "Carga de fotograma interrumpida". ¿Cómo puedo deshacerme de eso? No sucede cuando tengo el sistema operativo manejar la solicitud desde -webView:shouldStartLoadWithRequest:navigationType:, por lo que es un poco molesto.

¿Cómo se manejar tales peticiones?

Respuesta

88

Esto es lo que se me ocurrió. En webView:shouldStartLoadWithRequest:navigationType:, pido el sistema operativo para manejar cualquier no-http y https no solicita que se puede, de este modo:

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

    // Determine if we want the system to handle it. 
    NSURL *url = request.URL; 
    if (![url.scheme isEqual:@"http"] && ![url.scheme isEqual:@"https"]) { 
     if ([[UIApplication sharedApplication]canOpenURL:url]) { 
      [[UIApplication sharedApplication]openURL:url]; 
      return NO; 
     } 
    } 
    return YES; 
} 

Esto funciona muy bien a excepción de la sangrienta "Bastidor Interrumpida" error. Pensé que al devolver falso desde webView:shouldStartLoadWithRequest:navigationType:, la vista web no cargaría la solicitud y, por lo tanto, no habría ningún error que manejar. Pero a pesar de que devuelvo NO arriba, sigo con el error "Frame Load Interrupted". ¿Porqué es eso?

De todos modos, estoy asumiendo que puede ser ignorado en -webView:didFailLoadWithError::

- (void)webView:(UIWebView *)wv didFailLoadWithError:(NSError *)error { 
    // Ignore NSURLErrorDomain error -999. 
    if (error.code == NSURLErrorCancelled) return; 

    // Ignore "Fame Load Interrupted" errors. Seen after app store links. 
    if (error.code == 102 && [error.domain isEqual:@"WebKitErrorDomain"]) return; 

    // Normal error handling… 
} 

Y ahora las URL de iTunes funcione correctamente, al igual que mailto: s y enlaces de aplicaciones.

+1

No solo iTunes: también tuve esto con el inicio de sesión de Facebook a través de vistas web. – Adam

+0

Esto funcionó muy bien para mí también, gracias! – spstanley

+0

salvar mi día, muchas gracias – duan

-2

¿Te ayuda si registras tu aplicación para manejar itms: enlaces?

p. Ej. http://inchoo.net/iphone-development/launching-application-via-url-scheme/

Puede comenzar con el esquema http pero a continuación, obtener una redirección itms, lo que podría fallar si su aplicación no está registrada como el manejo de ese esquema.

+1

No quiero que mi aplicación maneje el esquema 'itms'. Quiero saber cuando alguien hace clic en un enlace en un UIWebView que la vista no puede manejar, y luego verifica si iOS puede manejarlo, y si lo hace, que lo haga.Nada que ver con si he registrado o no un esquema de URL para mi propia aplicación. – theory

+0

No hay forma de saber con solo mirar la URL. Manejar la falla (como mostraste) es probablemente la mejor manera. Sospecho que "Frame Load Interrupted" podría provenir de un redireccionamiento a un esquema URL de itms, por lo que sugerí registrar tu aplicación como apta. –

8

Comenzando con el código de Theory, examine la URL para esquema (s) "itms" (este método se puede llamar varias veces debido a redirecciones). Una vez que vea un esquema de "itms", detenga la carga de webView y abra la URL con Safari. Mi WebView pasa a estar en un NavigationController, así que salgo de eso después de abrir Safari (menos flasheo).

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request 
    navigationType:(UIWebViewNavigationType)navigationType 
{ 
    if ([[[request URL] scheme] isEqualToString:@"itms-apps"]) { 
     [webView stopLoading]; 
     [[UIApplication sharedApplication] openURL:[request URL]]; 
     [self.navigationController popViewControllerAnimated:YES]; 
     return NO; 
    } else { 
     return YES; 
    } 
} 
+0

En iOS 6.0 obtengo el esquema como "itmss" – cynistersix

+0

En iOS 9 el esquema es "itms-appss" –

Cuestiones relacionadas