NSURLSession 下载任务-进度条问题

NSURLSession Download Task- Progress Bar Issue

我正在处理一个非 ARC 项目,我必须在其中下载视频,下载后我将显示它们。我正在使用 NSURLSession 下载它。

问题出在进度条中。当我开始下载第四个文件时,我可以通过进度条正确下载前两个或三个文件,进度条没有正确更新,但文件正在下载上次删除的文件。

再次删除并重新下载时出现崩溃

试图在已失效的会话中创建任务

 - (void)startOrPauseDownloadingSingleFile : (UIButton *)sender
  {
    self.part_id_Value = self.part_id;
    m_Web getIconPathForAnimation:self.part_id];

     [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
      NSURL *urlVideo=[NSURL URLWithString:self.NonInteractiveMP4URL];
      NSString *strlastcomponent=[urlVideo lastPathComponent];


      FileDownloadInfo *fdi = [[FileDownloadInfo alloc] initWithFileTitle:strlastcomponent andDownloadSource:[NSString stringWithFormat:@"%@",urlVideo]];



        if (!fdi.isDownloading)
        {
            // Check if should create a new download task using a URL, or using resume data.


            if (fdi.taskIdentifier == -1)
            {
             **Getting Crash Here**

                fdi.downloadTask = [self.session downloadTaskWithURL:[NSURL URLWithString:fdi.downloadSource]];
            }
            else
            {
                fdi.downloadTask = [self.session downloadTaskWithResumeData:fdi.taskResumeData];
            }

            // Keep the new taskIdentifier.
            fdi.taskIdentifier = fdi.downloadTask.taskIdentifier;

            // Start the download.
            [fdi.downloadTask resume];

            // Indicate for each file that is being downloaded.
            fdi.isDownloading = YES;
        }
    }

我的下载更新进度条的方法-

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
 {
   double Progress = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
   NSLog(@"Progressview progress : %f",Progress);

if (totalBytesExpectedToWrite == NSURLSessionTransferSizeUnknown)
{
    NSLog(@"Unknown transfer size");
}
else
{
    [self performSelectorOnMainThread:@selector(updateProgress:) withObject:[NSString stringWithFormat:@"%f",Progress] waitUntilDone:NO];
 }
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
 {
 NSError *error;
 NSFileManager *fileManager = [NSFileManager defaultManager];
 NSString *destinationFilename = downloadTask.originalRequest.URL.lastPathComponent;
 NSURL *destinationURL = [self.docDirectoryURL URLByAppendingPathComponent:destinationFilename];

 if ([fileManager fileExistsAtPath:[destinationURL path]])
 {
    [fileManager removeItemAtURL:destinationURL error:nil];
 }
 BOOL success = [fileManager copyItemAtURL:location
                                    toURL:destinationURL
                                    error:&error];
 if (success)
  {
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        NSLog(@"Download completed!");
        NSLog(@"destination file name : %@!",destinationFilename);
        NSLog(@"Part id of file name : %@!",self.part_id);
        [self performSelectorOnMainThread:@selector(updateProgress:) withObject:[NSString stringWithFormat:@"1.0"] waitUntilDone:NO];

        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

        NSString *filenameValue=[NSString stringWithFormat:@"%@",destinationFilename];
        NSString *hideExtension=[filenameValue substringToIndex:filenameValue.length-4];
        NSLog(@"filenameValue == %@", filenameValue);

        [self DBUpdateVideoURLStatus:self.part_id andFileName:filenameValue];
        [self DBInsertDownloads:self.part_id andFileName:filenameValue];

        UIAlertView *alert=[[UIAlertView alloc]initWithTitle:NSLocalizedString(@"Success", @"Success message") message:[NSString localizedStringWithFormat:@"%@ downloaded successfully!",hideExtension] delegate:self cancelButtonTitle:NSLocalizedString(@"Ok", @"Ok action") otherButtonTitles:nil];
        alert.tag = 1;
        [alert show];
        [alert release];
        [self.session finishTasksAndInvalidate];
    }];
 }
 else
  {
    NSLog(@"Unable to copy temp file. Error: %@", [error localizedDescription]);
  }
}

-(void)updateProgress:(id)progress
{
  float currentProgress = [progress floatValue];
  [self.downloadProgress setProgress:currentProgress animated:YES];
  [self.downloadProgress setNeedsDisplay];
  [self.tblview reloadData];
}

嗯,我注意到一个错误:

mainQueue 在主线程上处理,因此您不应从在主队列上执行的块中调用 performSelectorOnMainThread。

在下载任务结束时到达主线程的标准模式是将异步分派到主队列,而不是像您所做的那样向 mainQueue 添加操作。

能否请您尝试更改以下代码并让我们知道结果:

-(void)updateProgress:(id)progress
{
    dispatch_async(dispatch_get_main_queue(), ^{

        float currentProgress = [progress floatValue];
        [self.downloadProgress setProgress:currentProgress animated:YES];
        [self.downloadProgress setNeedsDisplay];

    });
    [self.tblview reloadData];
}

你说:

When i am trying to download and delete it and again download Attempted to create a task in a session that has been invalidated *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Task created in a session that has been invalidated'

这是因为您正在调用 finishTasksAndInvalidate,它告诉 NSURLSession 它不仅应该完成所有队列任务,而且还应该使会话无效并且不允许任何更多任务。但是 运行 还有另一个任务,但是您使会话无效。

最重要的是,可以随意取消任务,但如果您要为同一会话对象启动更多任务,请不要使会话对象无效。