当我终止应用程序时,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
几个观察结果:
-
错误-999是
kCFURLErrorCancelled
。 -
如果您正在使用
NSURLSessionDownloadTask
,您可以使用后台会话配置在后台下载,例如NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:kBackgroundIdentifier]; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
如果不使用后台会话(例如,你必须使用数据任务),你可以使用
beginBackgroundTaskWithExpirationHandler
为应用程序请求一点时间——在应用程序终止之前,在后台完成请求。 -
请注意,当使用后台会话时,应用程序代理必须响应
handleEventsForBackgroundURLSession
,捕获它将在适当时调用的完成处理程序(例如,通常在URLSessionDidFinishEventsForBackgroundURLSession
中)。 -
你是如何"终止应用程序"的?如果你手动杀死它(双击主页按钮,按住运行应用程序的图标,然后点击红色的"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.)
有些事情我不能理解。这种行为让我疯了!:-(