NSURLSession中所有NSURLSessionTasks的平均进度 [英] Average progress of all the NSURLSessionTasks in a NSURLSession

查看:404
本文介绍了NSURLSession中所有NSURLSessionTasks的平均进度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

NSURLSession 将允许您添加大量 NSURLSessionTask 以在后台下载。



如果您想检查单个 NSURLSessionTask 的进度,就像



double taskProgress =(double)task.countOfBytesReceived /(double)task.countOfBytesExpectedToReceive;


$ b b

但是,在 NSURLSession 所有 NSURLSessionTasks > ?



我以为我会尝试平均所有任务的进度:

  [[self backgroundSession] getTasksWithCompletionHandler:^(NSArray * dataTasks,NSArray * uploadTasks,NSArray * allDownloadTasks){

double totalProgress = 0.0;

for(NSURLSessionDownloadTask * task in allDownloadTasks){

double taskProgress =(double)task.countOfBytesReceived /(double)task.countOfBytesExpectedToReceive;

if(task.countOfBytesExpectedToReceive> 0){
totalProgress = totalProgress + taskProgress;
}
NSLog(@task%d:%.0f /%。0f - %.2f %%,task.taskIdentifier,(double)task.countOfBytesReceived,(double)task.countOfBytesExpectedToReceive, taskProgress * 100);
}

double averageProgress = totalProgress /(double)allDownloadTasks.count;

NSLog(@总进度:%.2f,平均进度:%f,totalProgress,averageProgress);
NSLog(@);

}];

但是这里的逻辑是错误的:假设你有50个任务需要下载1MB和3个任务期望下载100MB。如果50个小任务在3个大任务之前完成, averageProgress 将大大高于实际的平均进度。



因此,您必须根据 TOTAL countOfBytesReceived TOTAL countOfBytesExpectedToReceive 。但问题是 NSURLSessionTask 只有在开始时才计算出这些值,并且它可能不会开始,直到另一个任务完成。



那么如何在所有 NSURLSessionTasks > NSURLSession

解决方案

在开始下载文件之前,您可以发送微小的 HEAD请求获取文件大小。您只需添加他们的 expectedContentLength ,并具有最终下载大小。

   - (void)sizeTaskForURL:(NSURL *)url 
{

NSMutableURLRequest * request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:@HEAD];

NSURLSessionDataTask * sizeTask =
[[self class] dataSession]
dataTaskWithRequest:request
completionHandler:^(NSData * data,NSURLResponse * response,NSError * error )
{
if(error == nil)
{
NSHTTPURLResponse * httpResponse =(NSHTTPURLResponse *)response;

if([httpResponse statusCode] == 200){

totalBytesExpectedToReceive + =(double)[httpResponse expectedContentLength];

numberOfFileSizesReceived ++;

NSLog(@%lu /%lu files found。file size:%f,(unsigned long)numberOfFileSizesReceived,(unsigned long)numberOfTasks,totalBytesExpectedToReceive);

if(numberOfFileSizesReceived == numberOfTasks){
NSLog(@%lu /%lu文件已找到,总文件大小:%f,(unsigned long)numberOfFileSizesReceived, numberOfTasks,totalBytesExpectedToReceive);
}
}
else {
NSLog(@URL状态下的大小任务的状态代码(%ld)%@,(长)[httpResponse statusCode] [response URL] absoluteString]);
}
}
else
{
NSLog(@Size task finished with error:%@,error.localizedDescription);
}
}];

[sizeTask resume];

}

之后下载文件



这是它的样子:



左边你可以看到当它发送 HEAD请求它尚未启动 UIProgressView 。当它完成后,它下载文件。





所以如果你下载大文件,它可能是有用的浪费那些秒,使HEAD请求,从而向用户显示正确的进度,而不是一些错误的进展。 / p>

在下载过程中,你(绝对)想使用委托方法获得新数据的更小的细分(否则进度视图将跳转)。

An NSURLSession will allow you to add to it a large number of NSURLSessionTask to download in the background.

If you want to check the progress of a single NSURLSessionTask, it’s as easy as

double taskProgress = (double)task.countOfBytesReceived / (double)task.countOfBytesExpectedToReceive;

But what is the best way to check the average progress of all the NSURLSessionTasks in a NSURLSession?

I thought I’d try averaging the progress of all tasks:

[[self backgroundSession] getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *allDownloadTasks) {

    double totalProgress = 0.0;

    for (NSURLSessionDownloadTask *task in allDownloadTasks) {

        double taskProgress = (double)task.countOfBytesReceived / (double)task.countOfBytesExpectedToReceive;

        if (task.countOfBytesExpectedToReceive > 0) {
            totalProgress = totalProgress + taskProgress;
        }
        NSLog(@"task %d: %.0f/%.0f - %.2f%%", task.taskIdentifier, (double)task.countOfBytesReceived, (double)task.countOfBytesExpectedToReceive, taskProgress*100);
    }

    double averageProgress = totalProgress / (double)allDownloadTasks.count;

    NSLog(@"total progress: %.2f, average progress: %f", totalProgress, averageProgress);
    NSLog(@" ");

}];

But the logic here is wrong: Suppose you have 50 tasks expecting to download 1MB and 3 tasks expecting to download 100MB. If the 50 small tasks complete before the 3 large tasks, averageProgress will be much higher than the actual average progress.

So you have to calculate average progress according to the TOTAL countOfBytesReceived divided by the TOTAL countOfBytesExpectedToReceive. But the problem is that a NSURLSessionTask figures out those values only once it starts, and it might not start until another task finishes.

So how do you check the average progress of all the NSURLSessionTasks in a NSURLSession?

解决方案

Before you start downloading the files you can send tiny small HEAD requests to get the file-sizes. You simply add their expectedContentLength and have your final download size.

- (void)sizeTaskForURL:(NSURL *)url
{

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
    [request setHTTPMethod:@"HEAD"];

    NSURLSessionDataTask *sizeTask =
    [[[self class] dataSession]
     dataTaskWithRequest:request
     completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error)
     {
         if (error == nil)
         {
             NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;

             if ([httpResponse statusCode] == 200) {

                 totalBytesExpectedToReceive += (double)[httpResponse expectedContentLength];

                 numberOfFileSizesReceived++;

                 NSLog(@"%lu/%lu files found. file size: %f", (unsigned long)numberOfFileSizesReceived, (unsigned long)numberOfTasks, totalBytesExpectedToReceive);

                 if (numberOfFileSizesReceived == numberOfTasks){
                     NSLog(@"%lu/%lu files found. total file size: %f", (unsigned long)numberOfFileSizesReceived, (unsigned long)numberOfTasks, totalBytesExpectedToReceive);
                 }
             }
             else {
                 NSLog(@"Bad status code (%ld) for size task at URL: %@", (long)[httpResponse statusCode], [[response URL] absoluteString]);
             }
         }
         else
         {
             NSLog(@"Size task finished with error: %@", error.localizedDescription);
         }
     }];

    [sizeTask resume];

}

Download the files afterwards

This is how it looks like:

On the left you can see that when it sends the HEAD requests it does not yet start the UIProgressView. When it has finished it downloads the files.

So if you download large files it might be useful to "waste" those seconds making HEAD requests and henceforth show the user the correct progress instead of some wrong progress.

During the downloads, you (definitely) want to use the delegate methods to get smaller subdivisions of new data (otherwise the progress view will "jump").

这篇关于NSURLSession中所有NSURLSessionTasks的平均进度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆