gpt4 book ai didi

ios - 使用 NSURLSessionDownloadTask 一个一个地下载文件

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:03:29 25 4
gpt4 key购买 nike

在我的应用程序中,我从 Web 服务获取 JSON。此 JSON 包含我要下载的几个文件的网址。

我想使用 NSURLSessionDownloadTask 一个一个地下载每个文件(等待第一个下载完成,直到第二个开始,依此类推)。我还想跟踪写入的总字节数,以便更新 UI。

提前致谢!

最佳答案

众所周知,NSURLSessionDownloadTask 不能很好地与 NSOperationQueues 一起使用,不像它们的对应物 NSURLConnection(它可以封装在 NSOperation 中)。

一个选择是将所有 url 添加到一个数组,然后在任务的 completionHandler 中,简单地将下一个项目放入队列。

因此,您可以在循环中创建任务,在每个任务完成处理程序中调用 progressBlock,将任务存储在数组中,并在每个任务完成处理程序中对下一个任务进行排队:

- (void)addRequestsWithURLs:(NSArray *)urls
progressBlock:(void (^)(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations, NSURLSessionDownloadTask *task,NSURL *location, NSURLResponse *response, NSError *error))progressBlock {
__block NSUInteger numberOfFinishedOperations = 0;
NSUInteger totalNumberOfOperations = [urls count];
for (NSString *url in urls) {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
__block NSURLSessionDownloadTask *task = [self.session downloadTaskWithRequest:request
completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
//downloadFileSomewhere

++numberOfFinishedOperations;
if (progressBlock) {
progressBlock(numberOfFinishedOperations, totalNumberOfOperations,task,destination != nil ? [NSURL fileURLWithPath:destination] : nil,response,error);

}
//queueNext
[self processCompletedTask:task];
}];
//stores an array of NSURLSessionTasks
[self.tasksWaitingToBeQueued addObject:task];
}

}

- (void)processCompletedTask:(NSURLSessionTask *)completedTask {
//clean up and queue next one
[self.tasksWaitingToBeQueued removeObject:completedTask];
nextTask = [self.tasksWaitingToBeQueued firstObject];
if (nextTask) {
[nextTask resume];
}
}

注意

在这个例子中,我将进度显示为完成的任务数而不是字节数,这是推荐的方法(它也更简单)。要使用字节指示进度,您需要事先知道要下载的字节总数(因为您要显示进度条),还需要实现 NSURLSession 委托(delegate)并监视每个任务的进度,捕获下载的字节并更新您的 block .如果您的服务器没有告诉您总字节数,那么您可能需要对每个资源执行 HEAD 请求并汇总大小。就个人而言,此解决方案过于复杂,因为可以通过指示下载文件数量的进度来简单地解决问题。

要实现这一点可能看起来像这样:

- (void)URLSession:(NSURLSession *)session 
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
self.totalBytesWritten += totalBytesWritten;
NSUInteger totalProgressSoFar = self.totalBytesWritten;
NSUInteger totalExpectedBytes = self.totalExpectedBytes;
//you would need to capture some progress block locally - beware of retain cycles
self.progressBlock(totalProgressSoFar/totalExpectedBytes)
}

完成后,您应该将 progressBlock 设置为 nil 到 prevent any retain cycles .

关于ios - 使用 NSURLSessionDownloadTask 一个一个地下载文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26297367/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com