【问题标题】:Handling NSURLSessionDownloadTask failure处理 NSURLSessionDownloadTask 失败
【发布时间】:2014-06-24 05:06:04
【问题描述】:

最初我认为如果NSURLSessionDownloadTask 成功完成URLSession:downloadTask:didFinishDownloadingToURL: 方法将被调用,如果由于某种原因失败 - URLSession:task:didCompleteWithError:。 它在模拟器上按预期工作(一个下载任务只调用此方法中的一个),但在设备上情况并非如此:如果失败,这两种方法都会被调用,URLSession:downloadTask:didFinishDownloadingToURL: 是第一个。 (这两种方法都在参数中传递相同的任务)

我有什么遗漏吗?

【问题讨论】:

  • 我注意到 DidFinishDownloadingToURL 与 didCompleteWithError 一起调用的行为相同。这给我们带来了巨大的问题。你是如何解决这个问题的?
  • location 在这种情况下可能为零。你能检查一下吗?

标签: ios objective-c nsurlsession nsurlsessiondownloadtask nsurlsessiontask


【解决方案1】:

使用完成块代替委托:

NSURLSessionDownloadTask *mySessionDownloadTask = [myURLSession downloadTaskWithRequest:myRequest completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error)
{
   dispatch_async(dispatch_get_main_queue(), ^{
      if(!error)
       {
           // Finish loading
       }
      else
       {
              // Handle error
        });
}];

注意:如果你没有得到主队列,任何与用户界面相关的更新都会被延迟,从而导致意想不到的行为。

【讨论】:

  • 我希望我的用户在我的应用进入后台模式时完成下载,所以我不能使用完成块代替委托(因为我正在使用后台会话)
  • 我明白了。那么如何使用全局 BOOL 来了解您是否已处理响应?
  • 嗯,当然可以有一个解决方法,但我想要更深入的了解。这是预期的行为还是应该报告的错误等。顺便说一句,BOOL 标志不是这里的最佳选择,因为在URLSession:downloadTask:didFinishDownloadingToURL:(首先调用)中,通常将文件复制到文档目录用于进一步处理。很高兴知道下载是成功完成还是出错。
【解决方案2】:

NSURLSessionDownloadTaskNSURLSessionTask 的子类,它具有error 属性。在您尝试复制文件之前,您能否在您的 URLSession:downloadTask:didFinishDownloadingToURL: 委托方法中检查一下?

【讨论】:

  • error 属性保持为 nil,除非它是客户端错误。
【解决方案3】:

根据NSURLSessionDownloadDelegate 下的Apple 文档,这是标准行为。

/* Sent when a download task that has completed a download.  The delegate should 
 * copy or move the file at the given location to a new location as it will be
 * removed when the delegate message returns. URLSession:task:didCompleteWithError: 
 * will still be called. */

【讨论】:

    【解决方案4】:

    我找到了解决这个问题的方法:

    要获取响应头中的状态码,您必须首先启动一个NSURLSessionDataTask

    这将调用以下委托方法URLSession:dataTask:didReceiveResponse:completionHandler:

    在此方法中,您可以首先检查 NSURLResponse 参数的状态代码(通过将其转换为 NSHTTPURLResponse),最后使用 NSURLSessionResponseBecomeDownload 调用完成处理程序将您的 dataTask 转换为 downloadTask (它的行为与您对 NSURLSessionDownloadTask) 或 NSURLSessionResponseCancel 的预期相同,以避免下载一些您不需要的数据(例如,如果响应的状态代码为 404)。

    另外,如果您需要对转换后的 NSURLSessionDownloadTask 做一些事情(比如将其存储在数组或字典中或用新对象替换数据任务),可以在 URLSession:dataTask:didBecomeDownloadTask 中完成:

    希望这对某人有所帮助!

    【讨论】:

      【解决方案5】:

      如果您正在执行 HTTP 请求,则可以将任务的响应转换为 NSHTTPURLResponse 以获取 HTTP 状态代码:

      -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL )location { NSLog(@"response is %d\n" ((NSHTTPURLResponse)downloadTask.response).statusCode); NSLog(@"error is %@\n", [downloadTask.error localizedDescription]); }

      Apple 的逻辑是当你得到一个 404 时,error 仍然是 null。

      【讨论】:

        猜你喜欢
        • 2016-06-30
        • 1970-01-01
        • 2011-07-15
        • 2012-05-10
        • 2014-08-28
        • 2011-08-12
        • 2020-06-10
        • 2011-04-26
        • 1970-01-01
        相关资源
        最近更新 更多