¿Cómo manejar las URL de la aplicación en una UIWebView?

Recientemente encontré que mi UIWebView se estaba atragantando con los enlaces ITMS. Específicamente, desde el UIWebView en mi aplicación, si navego a un sitio como este y hago clic en el enlace "Disponible en la App Store", UIWebView se equivocaría con "Error Domain = WebKitErrorDomain Code = 101 La URL no puede ser mostrado."

Después de un poco de Google, me di count de que necesitaba atrapar requestes de enlaces de aplicaciones y hacer que iOS las manejara. Comencé mirando para ver si el esquema comienza con "itms" en -webView:shouldStartLoadWithRequest:navigationType: pero se dio count de que podría haber otros types de enlaces de aplicaciones que el sistema puede manejar. Entonces se me ocurrió esto, en cambio:

 - (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 shanetworkingApplication]canOpenURL:url]) { [[UIApplication shanetworkingApplication]openURL:url]; return; } // Normal error handling… } 

Tengo dos preguntas sobre esto:

  1. ¿Esto es bueno? Estoy buscando específicamente el dominio de error y el código de error y obtengo la cadena URL de userInfo. ¿Es probable que eso siga así?
  2. Esto funciona para el enlace de tienda de aplicaciones vinculado anteriormente, pero cuando vuelvo a mi aplicación, parece haber una request fallida posterior que falló con "Carga de marco interrumpida". ¿Cómo puedo deshacerme de eso? No sucede cuando hago que el SO maneje la request desde -webView:shouldStartLoadWithRequest:navigationType: por lo que es un poco molesto.

¿Cómo maneja esas requestes?

Esto es lo que se me ocurrió. En webView:shouldStartLoadWithRequest:navigationType: le pido al sistema operativo que maneje cualquier request que no sea https y no https que pueda, así:

 - (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 shanetworkingApplication]canOpenURL:url]) { [[UIApplication shanetworkingApplication]openURL:url]; return NO; } } return YES; } 

Esto funciona muy bien, excepto por el sangriento error "Load Load Interrupted". Había pensado que devolviendo falso desde webView:shouldStartLoadWithRequest:navigationType: que la vista web no cargaría la request y, por lo tanto, no habría errores que manejar. Pero a pesar de que devuelvo NO arriba, todavía tengo el error "Frame Load Interrupted". ¿Porqué es eso?

De todos modos, -webView:didFailLoadWithError: que se puede ignorar 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 funcionan correctamente, al igual que los enlaces mailto: s y de aplicaciones.

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

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

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

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

Puede comenzar con el esquema http pero luego get una networkingirección de itms , que podría fallar si su aplicación no está registrada como el event handling ese esquema.