NSURLDomainErrorDomain错误-当应用程序使用NSURLSession终止时为999



当我终止应用程序时,NSURLSession遇到了大问题。我已经下载了苹果样品:https://developer.apple.com/library/ios/samplecode/SimpleBackgroundTransfer/Introduction/Intro.html

苹果参考资料。

当我开始下载文件时,请正确下载。当我在后台输入时,下载将继续。当我终止应用程序并重新启动应用程序时,应用程序进入:

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error

我发现了这个错误:

The operation couldn't be completed. (NSURLErrorDomain error -999.)

当应用程序终止时,我似乎无法恢复下载。这是正确的吗?为了继续下载,我必须让应用程序在后台处于活动状态?

谢谢Andrea

几个观察结果:

  1. 错误-999是kCFURLErrorCancelled

  2. 如果您正在使用NSURLSessionDownloadTask,您可以使用后台会话配置在后台下载,例如

    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:kBackgroundIdentifier];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
    

    如果不使用后台会话(例如,你必须使用数据任务),你可以使用beginBackgroundTaskWithExpirationHandler为应用程序请求一点时间——在应用程序终止之前,在后台完成请求。

  3. 请注意,当使用后台会话时,应用程序代理必须响应handleEventsForBackgroundURLSession,捕获它将在适当时调用的完成处理程序(例如,通常在URLSessionDidFinishEventsForBackgroundURLSession中)。

  4. 你是如何"终止应用程序"的?如果你手动杀死它(双击主页按钮,按住运行应用程序的图标,然后点击红色的"x"),这不仅会终止应用程序,还会停止后台会话。或者,如果应用程序崩溃,或者因为前台应用程序需要更多内存而被丢弃,后台会话将继续。

    就我个人而言,每当我想在应用程序终止后测试后台操作时,我的应用程序中都有崩溃的代码(尊重nil指针,就像苹果在WWDC视频中介绍NSURLSession一样)。显然,你永远不会在生产应用程序中这样做,但很难模拟由于内存限制而丢弃的应用程序,因此故意崩溃是这种情况的一个很好的代理。

我插入这几行新代码:

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    BLog();
    NSInteger errorReasonNum = [[error.userInfo objectForKey:@"NSURLErrorBackgroundTaskCancelledReasonKey"] integerValue];
    if([error.userInfo objectForKey:@"NSURLErrorBackgroundTaskCancelledReasonKey"] &&
       (errorReasonNum == NSURLErrorCancelledReasonUserForceQuitApplication ||
        errorReasonNum == NSURLErrorCancelledReasonBackgroundUpdatesDisabled))
    {
        NSData *resumeData = error.userInfo[NSURLSessionDownloadTaskResumeData];
        if (resumeData) {
            // resume
            NSURL *downloadURL = [NSURL URLWithString:DownloadURLString];
            NSURLRequest *request = [NSURLRequest requestWithURL:downloadURL];
            if (!self.downloadTask) {
                self.downloadTask = [self.session downloadTaskWithRequest:request];
                         }
            [self.downloadTask resume];
            if (!_session){
               [[_session downloadTaskWithResumeData:resumeData]resume];
                                         }
        }
    }
}

它捕获NSURLErrorCancelled ReasonUserForceQuitApplication,但当应用程序尝试[[_session downloadTaskWithResumeData:resumeData]resume]时

再次进入:

  • (void)URLSession:(NSURLSession*)会话任务:(NSURLSessionTask*)任务didCompleteWithError:(NSError*)error{

再给我一次-999错误。

我使用此配置

- (NSURLSession *)backgroundSession
{
/*
 Using disptach_once here ensures that multiple background sessions with the same identifier are not created in this instance of the application. If you want to support multiple background sessions within a single process, you should create each session with its own identifier.
 */
    static NSURLSession *session = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.example.apple-samplecode.SimpleBackgroundTransfer.BackgroundSession"];
        session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
    });
    return session;
}

让我解释一下"终止应用程序"(在ios8中)的含义:

  • 双击主页按钮
  • 在我打开的应用程序上滑动
  • 应用从打开的应用列表中消失
  • 重新启动应用程序

当我重新打开应用程序时,我进入回调并出现错误

The operation couldn't be completed. (NSURLErrorDomain error -999.)

有些事情我不能理解。这种行为让我疯了!:-(

最新更新