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
?
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. –
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
@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é.) –