2013-10-03 4 views
4

J'étudie en utilisant NSURLSessionUploadTasks pour gérer le téléchargement en arrière-plan de quelques fichiers. La session est créée à l'aide:Est-ce que didReceiveResponse doit toujours être appelé pour NSURLSessionUploadTasks avec des délégués personnalisés?

_urlsession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration backgroundSessionConfiguration:identifier] delegate:self delegateQueue:nil]; 

Ceci est créé dans une classe qui est conforme à URLSessionDataTaskDelegate et définit spécifiquement:

– URLSession:dataTask:didReceiveResponse:completionHandler: 
– URLSession:dataTask:didBecomeDownloadTask: 
– URLSession:dataTask:didReceiveData: 

et les journaux à la console à chaque fois que l'un de ces délégués est appelé.

Ensuite, une tâche de téléchargement est créé avec le code suivant:

NSString *urlString = [NSString stringWithFormat:@"%@%@?filename=%@", HOST, UPLOAD_PATH, filename]; 
NSMutableURLRequest *attachmentUploadRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]]; 
attachmentUploadRequest.HTTPMethod = @"POST"; 
[attachmentUploadRequest addValue:@"application/binary" forHTTPHeaderField:@"Content-Type"]; 

NSURLSessionTask* task = [_urlsession uploadTaskWithRequest:attachmentUploadRequest fromFile:filePath]; 
task.taskDescription = 'upload'; 

Cependant, la séquence de callbacks délégué que je reçois est pas comme prévu:

URLSession:didReceiveChallenge:completionHandler:]:196: Respond with <NSURLCredential: 0x1cf4fe00>: 
URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:]:282: Task 'upload' sent 32768 bytes 
URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:]:282: Task 'upload' sent 48150 bytes 
URLSession:dataTask:didReceiveData:]:222: Task 'upload' got some data: 

Notamment, les données du corps est envoyé, comme prévu, mais il passe immédiatement à didReceiveData rappels de délégué, sans rappel didReceiveResponse auparavant. C'est un comportement inattendu pour moi: je m'attendais à recevoir des informations sur la réponse afin que je puisse correctement configurer les données, ou mieux encore, convertir la tâche en tâche de téléchargement pour sauvegarder la réponse dans un fichier.

Si la tâche de téléchargement est soumis à une session d'URL par défaut, puis didReceiveResponse est appelé, et je peux convertir avec succès la tâche à une tâche de téléchargement en arrière-plan.

Je ne trouve aucune indication dans la documentation d'Apple indiquant si didReceiveResponse doit être appelé pour NSURLSessionUploadTask s en arrière-plan. Il semble qu'ils devraient: la documentation pour NSURLSessionUploadTask indique qu'il s'agit d'une sous-classe de NSURLSessionDataTask avec de petites modifications dans le comportement, mais aucune des différences énumérées implique ne pas envoyer le rappel didReceiveResponse. Aucun document spécifique à la session d'arrière-plan ne mentionne cette limitation.

Est-ce un bug, ou avez-vous manqué/mal interprété une partie de la documentation qui explique que les tâches de téléchargement en arrière-plan n'appellent pas didReceiveResponse?

Répondre

6

J'ai demandé les ingénieurs d'Apple à ce sujet lors des récentes rencontres de Tech. Ils ont suivi et ont donné la réponse suivante - pas entièrement satisfaisante, et je pense qu'ils devraient documenter ce comportement s'il est différent de tout autre flux de gestion HTTP. D'autant plus que le comportement de premier plan obtient le didReceiveData, mais n'obtient pas le didReceiveResponse. À tout le moins, ils doivent documenter ce comportement non évident. "La façon dont les choses fonctionnent aujourd'hui est que nous n'envoyons pas le rappel de didReceiveResponse pour les téléchargements en arrière-plan afin d'éviter de réveiller l'application si elle n'est pas déjà en cours d'exécution. Notre décision était basée sur l'attente que les données de réponse pour un téléchargement de fichier seraient petites et donc livrer les données de réponse au client comme NSData au lieu d'un fichier téléchargé serait bien. "

+3

Qu'advient-il si une réponse non-200 est reçue et le corps est vide? Comment devons-nous recevoir et gérer cette réponse? S'il y a des données, peut-on supposer que didReceiveData n'est appelé qu'une seule fois? C'est un changement majeur par rapport au cycle de vie de tous les autres gestionnaires HTTP basés sur des délégués sur la plate-forme. Toutes les différences doivent être clairement documentées et expliquées. –

+0

Mise à jour - J'ai reçu une réponse d'Apple que je devrais tester à nouveau dans iOS 8.J'ai donc essayé, et ça n'a pas marché. Alors je suis allé chez les développeurs, puisque j'étais à la WWDC et je leur ai dit que le correctif ne fonctionnait pas. Il s'avère que le correctif était un commentaire dans l'en-tête qui dit que cela ne fonctionne pas (ce qui est une amélioration). J'ai appris pourquoi ils l'ont fait de cette façon, mais je pense toujours qu'ils pourraient, par courtoisie, appeler le didReceiveResponse et le rendre plus cohérent. Je fais toujours campagne pour cela. – snarshad

+1

@JasonLeBrun Si je comprends bien votre question, dans ce cas vous obtiendriez une URLSession: task: didCompleteWithError: callback sur votre délégué, avec la réponse dans task.response. (C'est dans le protocole NSURLSessionTaskDelegate, le protocole "parent" de celui que vous avez implémenté.) –

Questions connexes