2009-09-10 11 views
19

Necesito comprobar si una URL (representada por un NSURL) está disponible o devuelve 404. ¿Cuál es la mejor manera de lograr eso?Compruebe si NSURL devuelve 404

Preferiría una forma de verificar esto sin un delegado, si es posible. Necesito bloquear la ejecución del programa hasta que sepa si la URL es alcanzable o no.

Respuesta

38

Como usted puede saber ya que el error general puede capturar por el método didFailWithError:

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 
    NSLog(@"Connection failed! Error - %@ %@", 
      [error localizedDescription], 
      [[error userInfo] objectForKey:NSErrorFailingURLStringKey]); 
} 

pero para 404 "no encontrado" o 500 "Error interno del servidor" debe poder capturar el interior método didReceiveResponse:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 
    if ([response respondsToSelector:@selector(statusCode)]) 
    { 
     int statusCode = [((NSHTTPURLResponse *)response) statusCode]; 
     if (statusCode == 404) 
     { 
      [connection cancel]; // stop connecting; no more delegate messages 
      NSLog(@"didReceiveResponse statusCode with %i", statusCode); 
     } 
    } 
} 
+7

Tenga en cuenta que hay un método de la clase práctica en NSHTTPURLResponse para devolver una descripción localizado para el código de error: '[NSHTTPURLResponse localizedStringForStatusCode: [respuesta statusCode]]' –

+0

¿Es posible tener esto en Swift ..? Muchas gracias – ernestocattaneo

+3

Estoy seguro de que haces esto en la versión Swift. Convertir a mano no sería difícil. – Jirapong

2

Se puede lograr una conexión síncrona llamando:

NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]]; 
NSHTTPURLResponse* response = nil; 
NSError* error = nil; 
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; 

Su hilo se bloqueará hasta que se haya realizado la solicitud.

+0

Las solicitudes sincrónicas bloquean la GUI y también desperdician recursos. Asincrónico no lo hace y permite además un mejor manejo y cancelación de errores. – MacMark

+0

No, eso está mal. Si nada está en 'url', no bloqueará: NSURLConnection descargará el contenido de la página web 404. Pero puede verificar el código de estado con '[response statusCode]' – Martin

+0

@MacMark ¿Por qué supone que una solicitud síncrona bloqueará la GUI? ¿Qué pasa si lo he colocado cuidadosamente en una NSOperation que no lo hará? En ese momento, para responder a mi pregunta, ¿cómo "desperdician recursos" exactamente en comparación con una solicitud asincrónica?(Para el caso, ¿cómo permiten un mejor manejo de errores ... a menos que utilice el protocolo NSURlConnection en su lugar, que creo que todavía puede hacer si realmente lo desea, aunque es un poco más complicado y si ya ha enhebrado ¡la operación es completamente contraproducente y una pérdida de recursos en sí misma!) – RonLugge

29

Necesitaba una solución que no utilizara un delegado tampoco, así que tomé pedazos de código que se muestran en otras respuestas aquí y creé un método simple que funciona bien en mi caso (y podría ser lo que está buscando también):

-(BOOL) webFileExists { 

     NSString *url = @"http://www.apple.com/somefile.html"; 

     NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:5.0]; 
     NSHTTPURLResponse* response = nil; 
     NSError* error = nil; 
     [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; 
     NSLog(@"statusCode = %d", [response statusCode]); 

     if ([response statusCode] == 404) 
      return NO; 
     else 
      return YES; 
    } 
+1

Eso no es muy útil en archivos grandes. Descargará el archivo completo antes de devolver una respuesta –

+0

Esto funciona genial, gracias. Para otros que buscan hacer esto, puede considerar buscar un código de estado '200' para que sepa que su archivo es accesible, ya que podría ocurrir cualquier cantidad de errores además de un' 404' como '403 Forbidden' y' 500 Internal Server Error' . ¡Gracias! –

8

que utilizan la respuesta de woodmantech arriba, pero lo cambiaron en base a lo que he visto en otras cuestiones similares aquí para que no se descarga todo el archivo para ver si existe.

me cambiaron a NSURLRequestNSMutableURLRequest, y ha añadido:

[request setHTTPMethod:@"HEAD"]; 

Esto parece funcionar bien. Estoy trabajando en mi primera aplicación, por lo que aún no tengo experiencia real. Gracias a todos.

NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:5.0]; 
    [request setHTTPMethod:@"HEAD"]; 
    NSHTTPURLResponse* response = nil; 
    NSError* error = nil; 
    [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; 
    NSLog(@"statusCode = %d", [response statusCode]); 
+0

¡Excelente respuesta! – Omkar