如何获得AFNetworking 2.0的下载进度?

我正在使用AFURLSessionManager来创build一个新的下载任务:

AFURLSessionManager* manager = ... NSProgress* p = nil; NSURLSessionDownloadTask* downloadTask = [manager downloadTaskWithRequest:request progress:&p destination:^NSURL*(NSURL* targetPath, NSURLResponse* response) {...} completionHandler:^(NSURLResponse* response, NSURL* filePath, NSError* error) {...} ]; [downloadTask resume]; 

该文件得到下载罚款,但是,我怎么得到进展通知?

p总是设为零。 我为此提出了一个问题 。

我也尝试在pipe理器上调用setDownloadTaskDidWriteDataBlock ,并在那里获取进度通知,但是在文件下载完成 ,我将它们全部分组。

看起来这个区域在AFNetworking 2.0中还是有点bug的

有任何想法吗?

您应该使用KVO观察NSProgress对象的fractionCompleted属性:

 NSURL *url = [NSURL URLWithString:@"http://www.hfrmovies.com/TheHobbitDesolationOfSmaug48fps.mp4"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; AFHTTPSessionManager *session = [AFHTTPSessionManager manager]; NSProgress *progress; NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request progress:&progress destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) { // … } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) { [progress removeObserver:self forKeyPath:@"fractionCompleted" context:NULL]; // … }]; [downloadTask resume]; [progress addObserver:self forKeyPath:@"fractionCompleted" options:NSKeyValueObservingOptionNew context:NULL]; 

然后添加观察者方法:

 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"fractionCompleted"]) { NSProgress *progress = (NSProgress *)object; NSLog(@"Progress… %f", progress.fractionCompleted); } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } 

当然,你应该检查keyPath和/或object参数来决定是否你想要观察的对象/属性。

您还可以使用AFURLSessionManagersetDownloadTaskDidWriteDataBlock:方法( AFHTTPSessionManagerinheritance)来设置用于接收下载进度更新的块。

 [session setDownloadTaskDidWriteDataBlock:^(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) { NSLog(@"Progress… %lld", totalBytesWritten); }]; 

此AFNetworking方法将URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:方法从NSURLSessionDownloadDelegate协议NSURLSessionDownloadDelegate到更方便的块机制。

顺便说一句,苹果的KVO实施被严重打破。 我build议使用像MAKVONotificationCenter中 Mike Ash提出的更好的实现。 如果您有兴趣了解为什么苹果的KVO被破坏,请阅读Mike Ash的Key-Value Observing Done Right 。

我遇到了类似的问题,并find了解决办法。

检查下面的链接: http : //cocoadocs.org/docsets/AFNetworking/2.0.1/Categories/UIProgressView+AFNetworking.html

 #import <AFNetworking/UIKit+AFNetworking.h> 

并使用UIProgressView提供的附加方法

setProgressWithDownloadProgressOfTask:animation:

我是如何做到的:

 NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response){ NSURL *documentsDirectoryPath = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) firstObject]]; return [documentsDirectoryPath URLByAppendingPathComponent:[targetPath lastPathComponent]]; } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error){ NSLog(@"File downloaded to: %@", filePath); }]; [self.progressView setProgressWithDownloadProgressOfTask:downloadTask animated:YES]; [downloadTask resume]; 

Swift的简单解决scheme:

 let sessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration() let sessionManager = AFURLSessionManager(sessionConfiguration: sessionConfiguration) let request = NSURLRequest(URL: url) let sessionDownloadTask = sessionManager.downloadTaskWithRequest(request, progress: nil, destination: { (url, response) -> NSURL in return destinationPath.URLByAppendingPathComponent(fileName) //this is destinationPath for downloaded file }, completionHandler: { response, url, error in //do sth when it finishes }) 

现在你有两个select:

  1. 使用UIProgressViewsetProgressWithDownloadProgressOfTask:

     progressView.setProgressWithDownloadProgressOfTask(sessionDownloadTask, animated: true) 
  2. 使用AFURLSessionManagersetDownloadTaskDidWriteDataBlock:

     sessionManager.setDownloadTaskDidWriteDataBlock { session, sessionDownloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite in let progress = Float(totalBytesWritten)/Float(totalBytesExpectedToWrite) //do sth with current progress } 

最后不要忘记:

 sessionDownloadTask.resume() 

对于下载进度状态的文件,请使用此代码

  NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration]; NSURL *URL = [NSURL URLWithString:@"http://..."]; NSURLRequest *request = [NSURLRequest requestWithURL:URL]; NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) { NSLog(@"Progress: %f", downloadProgress.fractionCompleted); if (progressBlock) { progressBlock(downloadProgress); } } destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) { NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil]; return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]]; } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) { if (response && successBlock) { successBlock(response,filePath); } NSLog(@"File downloaded to: %@", filePath); }]; [downloadTask resume];