将NSURLSessionDataTask转换为具有后台支持的下载任务

时间:2014-04-25 12:26:24

标签: ios session download nsurlsession

我需要在检查标题(对于长度和类型)后,使用后台才能下载某些文件(不是所有文件),但它必须处于相同的操作中,而不是创建新的任务/请求(因为有时候由于在很短的时间内连接很多,我从服务器收到错误。 所以我开始任务:

NSURLSessionConfiguration *configuratione = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *sessione = [NSURLSession sessionWithConfiguration:configuratione delegate:self delegateQueue:nil];
NSURLSessionDataTask *datatask = [sessione dataTaskWithRequest:request];
[datatask resume];

然后,我知道可以在收到第一个响应时将数据任务转换为下载任务,并使用此委托:

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
{
    if(XXXXXXXXXX){
        NSLog(@"transform into a download");
        completionHandler(NSURLSessionResponseBecomeDownload);
    }else{
        NSLog(@"Keep loading normally");
        completionHandler(NSURLSessionResponseAllow);
    }
}

但是,由于Data Tasks无法使用BackgroundSessionConfiguration,我认为新创建的下载将使用相同的默认会话配置。 如何在后台运行下载?有没有办法将它的会话改为后台会话?或者哪种方法?

1 个答案:

答案 0 :(得分:10)

这个问题很难给出一个明确的答案,对我来说,所有3个主要的URLLoading因素(sessionType,taskType,FG / BG创建)都受到你的设计的限制。

由于会话在配置(确定默认/ BackGround / Ephemeral会话 - 自然类型)上保留了深层副本,因此在启动会话后(在我们的情况下:您的默认值 - type-Session)你不能再修改当前会话的配置对象。因此,如果您的设计不允许新的任务与新的(希望) BG类型会话相关联,那么就没有办法只能神奇地转换" dataTask"进入" downloadTask"。

请注意, NSURLSessionDataTask NSURLSessionDownloadTask 都是 NSURLSessionTask 的子类,NSURLSessionDataTask和NSURLSessionDownloadTask处理传入的响应数据(分别为VS文件)框架实现的方式非常不同。

一个有吸引力的错觉可能是这种有吸引力的方法URLSession:dataTask:didBecomeDownloadTask:,但您必须创建一个与当前相关联的新任务(DownloadTask in deed)(由您之前配置的深刻标记)默认类型)会话,并将原始任务(dataTask)保留为孤儿。我的理解是,由于额外创建任务,您的设计不能采用此选项,并且您必须保持默认类型会话配置。

URLSession:dataTask:didBecomeDownloadTask:应该真正命名为URLSession:dataTask:wasReplacedByDownloadTask:

我现在只有简单的解决方案是,在接收URLSession时,在Data-Task-Delegate (类实现NSURLSessionDataDelegate协议):dataTask:didReceiveData:初始调用,开始存储这些分段数据某种方式(存储到临时文件,也许,模拟NSURLSessionDownloadTask的默认操作),并确保在NSOperationQueue上异步执行此委托 (我猜你的"后台能力"表示辅助线程,可以由NSOperationQueue提供,强调线程机制),直到下载完成,然后检查存储中的累积结果(如果处理任何错误和/或者将文件转移到其他地方在这个通用的NSURLSessionTaskDelegate方法" URLSession:task:didCompleteWithError:"

这样做,您将请求(由NSURLSessionDataTask表示)转换为下载(不是NSURLSessionDownloadTask) 。为了满足此转换发生在后台队列上,为(委托/任务)此委托方法的最后一个参数提供非零值: - 否则,串行操作队列将无法满足您的"后台能力& #34;需要

NSOperationQueue* aQueue = [[NSOperationQueue alloc] init];

NSURLSession *sessione = [NSURLSession sessionWithConfiguration:configuratione delegate:self delegateQueue: aQueue];

其他想法将手动执行多个NSOperation对象,覆盖其启动方法以确保下载任务的异步执行,这可能有点棘手。

任何其他有更好解决方案的人,请带来更多火花......或纠正我可能产生的任何误导。