Average progress of all the NSURLSessionTasks in a NSURLSession

Viewed 6959

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?

4 Answers
Related