【问题标题】:Should didReceiveResponse always be called for NSURLSessionUploadTasks with custom delegates?是否应该始终为具有自定义委托的 NSURLSessionUploadTasks 调用 didReceiveResponse?
【发布时间】:2013-10-03 00:39:29
【问题描述】:

我正在研究使用 NSURLSessionUploadTasks 来管理一些文件的后台上传。会话是使用以下方式创建的:

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

这是在符合URLSessionDataTaskDelegate的类中创建的,具体定义:

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

每次调用其中一个委托时都会记录到控制台。

然后,使用以下代码创建一个上传任务:

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';

但是,我得到的委托回调序列并不像预期的那样:

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:

值得注意的是,正文数据按预期发送,但随后立即切换到 didReceiveData 委托回调,事先没有 didReceiveResponse 回调。这对我来说是一个意外的行为:我希望收到有关响应的信息,以便我可以正确设置数据,或者更好的是,将任务转换为下载任务以将响应保存到文件中。

如果上传任务是在默认 URL 会话中提交的,则调用 didReceiveResponse,我可以成功地将任务转换为后台下载任务。

我在 Apple 的文档中找不到任何迹象表明是否应该为后台的 NSURLSessionUploadTasks 调用 didReceiveResponse似乎他们应该这样做:NSURLSessionUploadTask 的文档表明它是 NSURLSessionDataTask 的子类,在行为上做了一些小的修改,但列出的差异都没有涉及不发送 didReceiveResponse 回调。没有一个特定于背景会话的文档提到这个限制。

这是一个错误,还是错过/误解了某些解释后台上传任务不调用didReceiveResponse的文档?

【问题讨论】:

    标签: delegates ios7 nsurlsession


    【解决方案1】:

    在最近的技术讲座中,我向 Apple 工程师询问了这个问题。他们跟进并给出了以下响应 - 并不完全令人满意,我觉得如果它与任何其他 HTTP 处理流程不同,他们应该记录这种行为。特别是因为前台行为确实获得了 didReceiveData,但没有获得 didReceiveResponse。至少他们需要记录这种不明显的行为。

    “今天的工作方式是我们不为后台上传发送 didReceiveResponse 回调,以避免唤醒尚未运行的应用程序。缺点是应用程序无法选择将后台上传转换为下载任务当收到响应时。我们的决定是基于预期文件上传的响应数据会很小,因此将响应数据作为 NSData 而不是下载的文件传递给客户端就可以了。"

    【讨论】:

    • 如果收到非 200 响应且正文为空会怎样?我们期望如何接收和处理此响应?如果有数据,我们可以假设 didReceiveData 只被调用一次吗?这与平台上所有其他基于委托的 HTTP 处理程序的生命周期有很大的不同。应清楚地记录和解释所有差异。
    • 更新 - 我收到了 Apple 的回复,我应该在 iOS 8 中再次对其进行测试。所以我尝试了,但没有成功。所以我去找开发人员,因为我在 WWDC 并告诉他们修复不起作用。事实证明,修复是标题中的一条评论,说它不起作用(这是一个改进)。我了解了他们为什么这样做的一些背景,但我仍然认为他们可以礼貌地调用 didReceiveResponse 并使其更加一致。我仍在为它竞选。
    • @JasonLeBrun 如果我正确理解了您的问题,在这种情况下,您将在您的委托上收到 URLSession:task:didCompleteWithError: 回调,并在 task.response 中响应。 (这在 NSURLSessionTaskDelegate 协议中,即您已实现的“父”协议。)
    • 这个(未记录的)功能浪费了我四个小时的时间。我希望苹果能解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    • 1970-01-01
    • 2014-11-02
    • 1970-01-01
    相关资源
    最近更新 更多