当我尝试使NSURLSession
实例无效时,我遇到了一个奇怪的问题。
代码很简单:我有一个View Controller,两个按钮(start:和stop :),以及一个url的文本字段。
代码的简单摘录:
- (IBAction)start:(id)sender {
NSURLSessionConfiguration *conf = [NSURLSessionConfiguration backgroundSessionConfiguration:@"conf"];
self.session = [NSURLSession sessionWithConfiguration:conf delegate:self delegateQueue:nil];
NSURLSessionDownloadTask *task = [self.session downloadTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.url.text]]];
[task resume];
}
- (IBAction)cancel:(id)sender {
[self.session invalidateAndCancel];
}
或者,如果您愿意,整个项目:Link
现在,尝试下载文件(http://download.thinkbroadband.com/1GB.zip)。
由于我希望此下载在后台继续,我正在使用后台会话
会话正确启动,下载在后台继续,但如果我尝试取消它(发送invalidateAndCancel
),我的访问权限很差。
使用Zombie进行性能分析会给出这个僵尸对象:_NSCFBackgroundDownloadTask
因此,如果我保留NSURLSessionDownloadTask
(使用强属性来存储它),则不会发生错误访问。
但是,AFAIK,NSURLSession应该保留它自己的任务,所以我想了解我的代码有什么问题(也许我在文档中遗漏了什么?)或者我应该提交bug报告。
由于
答案 0 :(得分:16)
请使用更好的后台会话配置标识符!这不是你的会话;后台会话是进入共享系统会话的一种网关。您需要将会话的任务与执行后台上载和下载的所有其他应用程序的任务区分开来。使用独特的内容,例如@"com.company.appname.specialname"
。
取消和使后台会话无效没有多大意义。你正在杀戮会议;在使其失效后,你永远不能再使用它。那太傻了。您要做的是在应用程序启动时创建一次后台会话,并将其永久保留在那里(作为共享系统会话的网关,如前所述)。如果要取消某些内容,您要取消的是任务。保留对该任务的引用,以便您可以对该引用说cancel
,如果您认为您想要取消它。或者,如果您真的不想保留对任务的引用,可以通过调用getTasksWithCompletionHandler:
向NSURLSession询问当前任务的列表;一个任务可以有一个标识符,所以找到你想要的那个并告诉它cancel
应该没有问题。
答案 1 :(得分:10)
经过多次调试后,我发现当代理没有实现以下NSURLSessionTaskDelegate
协议方法时会发生这种情况:
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
}
将此方法添加到委托可解决错误。 “奇怪”的是委托方法被标记为可选,所以它不是必需的。这让我觉得这是一个bug,所以我会提交一个bug报告。 我会等待几天以获得更完整的答案,如果没有人出现,我会将其作为正确答案。
编辑:
如果有人有兴趣,我创建一个帮助类项目来下载后台文件:Link To Project