NSURLConnection didReceiveData no llamado

He leído toneladas de posts diciendo lo mismo de nuevo: cuando utiliza una NSURLConnection, no se llaman los methods de delegado. Entiendo que los documentos de Apple están incompletos y los methods de reference en desuso, lo cual es una lástima, pero parece que no puedo encontrar una solución.

El código para la request está ahí:

// Create request NSURL *urlObj = [NSURL URLWithString:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:urlObj cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30]; [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"]; if (![NSURLConnection canHandleRequest:request]) { NSLog(@"Can't handle request..."); return; } // Start connection dispatch_async(dispatch_get_main_queue(), ^{ self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES]; // Edited }); 

… y el código para los methods de delegado está aquí:

 - (void) connection:(NSURLConnection *)_connection didReceiveResponse:(NSURLResponse *)response { NSLog(@"Receiving response: %@, status %d", [(NSHTTPURLResponse*)response allHeaderFields], [(NSHTTPURLResponse*) response statusCode]); self.data = [NSMutableData data]; } - (void) connection:(NSURLConnection *)_connection didFailWithError:(NSError *)error { NSLog(@"Connection failed: %@", error); [self _finish]; } - (void) connection:(NSURLConnection *)_connection didReceiveData:(NSData *)_data { [data appendData:_data]; } - (void)connectionDidFinishDownloading:(NSURLConnection *)_connection destinationURL:(NSURL *) destinationURL { NSLog(@"Connection done!"); [self _finish]; } 

Aquí no hay muchos errores, pero me aseguré de algunas cosas:

  • Pase lo que pase, didReceiveData nunca se llama, así que no obtengo ningún dato
  • … pero los datos se transfieren (revisé usando tcpdump )
  • … y los demás methods se invocan con éxito.
  • Si utilizo NSURLConnectionDownloadDelegate lugar de NSURLConnectionDataDelegate , todo funciona, pero no puedo controlar el file descargado (este es un error conocido)
  • La request no se desasigna antes de completarse por mala gestión de la memory
  • Nada cambia si uso una página HTML estándar en algún lugar de Internet como mi URL
  • La request se inicia desde la queue principal.

No quiero usar una biblioteca de terceros, ya que, en última instancia, estas requestes deben includese en una biblioteca propia, y me gustaría minimizar las dependencies. Si es necesario, CFNetwork directamente, pero será un gran dolor en el que sepas.

Si tienes alguna idea, sería de gran ayuda. ¡Gracias!

Me gusta usar el método sendAsynchronousRequest … hay less información durante la connection, pero el código es mucho más limpio.

  [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){ if (data){ //do something with data } else if (error) NSLog(@"%@",error); }]; 

Desde Apple:

De forma pnetworkingeterminada, una connection está progtwigda en el hilo actual en el modo pnetworkingeterminado cuando se crea. Si crea una connection con el método initWithRequest: delegate: startImmediately: método y proporciona NO para el parámetro startImmediately, puede progtwigr la connection en un ciclo o modo de ejecución diferente antes de iniciarlo con el método de inicio. Puede progtwigr una connection en varios ciclos y modos de ejecución, o en el mismo ciclo de ejecución en varios modos.

A less que exista una razón para ejecutarlo explícitamente en [NSRunLoop currentRunLoop], puede eliminar estas dos líneas:

 [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; [connection start]; 

o cambie el modo a NSDefaultRunLoopMode

Tuve el mismo problema. Muy molesto, pero parece que si implementas este método:

 - (void)connectionDidFinishDownloading:(NSURLConnection *)connection destinationURL:(NSURL *)destinationURL 

Luego connection:didReceiveData: nunca se llamará. Tienes que usar connectionDidFinishLoading: lugar … Sí, los documentos dicen que está en desuso, pero creo que es solo porque este método se movió de NSURLConnectionDelegate a NSURLConnectionDataDelegate .

NSURLConnection API dice "… los methods delegate se invocan en el subprocess que inició la operación de carga asincrónica para el object NSURLConnection asociado".

Como dispatch_async comenzará un nuevo subprocess, y NSURLConnection no pasará a esa otra amenaza que respalda la llamada, entonces no use dispatch_async con NSURLConnection.

No tiene miedo de la interfaz de usuario congelada, la NSURLConnection proporciona solo los controles de las cargas asíncronas.

Si tiene más files para download , puede iniciar algunas conexiones en el primer turno y luego finalizar, en el método connectionDidFinishLoading: puede iniciar nuevas conexiones.

 int i=0; for (RetrieveOneDocument *doc in self.documents) { if (i<5) { [[NSURLConnection alloc] initWithRequest:request delegate:self]; i++; } } .. -(void)connectionDidFinishLoading:(NSURLConnection *)connection { ii++; if(ii == 5) { [[NSURLConnection alloc] initWithRequest:request delegate:self]; ii=0; } } 

Una razón posible es que la NSURLRequest saliente se ha configurado para tener un -HTTPMethod de HEAD . Sin embargo, es bastante difícil hacerlo por crash.