NSURLConnection didReceiveData non appelé

J'ai lu des tonnes de messages en répétant la même chose: lorsque vous utilisez un NSURLConnection, les methods déléguées ne sont pas appelées . Je comprends que les doc d'Apple sont incomplètes et referencent les methods obsolètes, ce qui est dommage, mais je n'arrive pas à find une solution.

Le code de la request est là:

// Create request NSURL *urlObj = [NSURL URLWithSsortingng: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 }); 

… et le code pour les methods de délégué est ici:

 - (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]; } 

Il n'y a pas beaucoup de vérification d'erreur ici, mais j'ai vérifié certaines choses:

  • Quoi qu'il arrive, didReceiveData n'est jamais appelé, donc je ne reçois aucune donnée
  • … mais datatables sont transférées (j'ai vérifié en utilisant tcpdump )
  • … et les autres methods sont appelées avec succès.
  • Si j'utilise le NSURLConnectionDownloadDelegate place de NSURLConnectionDataDelegate , tout fonctionne mais je ne peux pas me retenir sur le file téléchargé (c'est un bug connu)
  • La request n'est pas libérée avant l'achèvement par une mauvaise memory management
  • Rien ne change si j'utilise une page HTML standard quelque part sur Internet comme URL
  • La requête est lancée depuis la queue principale

Je ne veux pas utiliser une bibliothèque tierce, car, en fin de count, ces requêtes doivent être incluses dans une bibliothèque, et j'aimerais minimiser les dependencies. Si je dois le faire, j'utiliserai CFNetwork directement, mais ce sera une énorme souffrance dans le vous-savez-quoi.

Si vous avez une idée, cela aiderait grandement. Merci!

J'aime utiliser la méthode sendAsynchronousRequest .. il y a less d'informations lors de la connection, mais le code est beaucoup plus propre.

  [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); }]; 

D'Apple:

Par défaut, une connection est planifiée sur le thread en cours dans le mode par défaut lors de sa création. Si vous créez une connection avec la méthode initWithRequest: delegate: startImmediately: et que vous indiquez NO pour le paramètre startImmediately, vous pouvez planifier la connection sur une boucle ou un mode d'exécution différent avant de la démarrer avec la méthode start. Vous pouvez planifier une connection sur plusieurs loops et modes d'exécution, ou sur la même boucle d'exécution dans plusieurs modes.

À less qu'il y ait une raison de l'exécuter explicitement dans [NSRunLoop currentRunLoop], vous pouvez supprimer ces deux lignes:

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

ou changez le mode en NSDefaultRunLoopMode

J'ai rencontré le même problème. Très ennuyeux, mais il semble que si vous implémentez cette méthode:

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

Puis connection:didReceiveData: ne sera jamais appelé. Vous devez utiliser connectionDidFinishLoading: place … Oui, les docs disent qu'il est déprécié, mais je pense que c'est seulement parce que cette méthode est passée de NSURLConnectionDelegate à NSURLConnectionDataDelegate .

L'API NSURLConnection indique "Les methods ..delegate sont appelées sur le thread qui a démarré l'opération de chargement asynchronous pour l'object NSURLConnection associé."

Parce que dispatch_async démarrera un nouveau thread, et NSURLConnection ne transmettra pas à cette autre menace le callback, donc n'utilisez pas dispatch_async avec NSURLConnection.

Vous n'avez pas à avoir peur de l'interface user gelée, NSURLConnection ne fournissant que les controls des charges asynchronouss.

Si vous avez plus de files à download , vous pouvez démarrer une partie de la connection au premier tour, et plus tard, dans la méthode connectionDidFinishLoading: vous pourrez commencer de nouvelles connections.

 int i=0; for (ResortingeveOneDocument *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; } } 

Une raison possible est que le NSURLRequest sortant a été configuré pour avoir un -HTTPMethod de HEAD . Assez difficile à faire par accident si!