如何获得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
参数来决定是否你想要观察的对象/属性。
您还可以使用AFURLSessionManager
的setDownloadTaskDidWriteDataBlock:
方法( AFHTTPSessionManager
inheritance)来设置用于接收下载进度更新的块。
[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:
-
使用
UIProgressView
和setProgressWithDownloadProgressOfTask:
progressView.setProgressWithDownloadProgressOfTask(sessionDownloadTask, animated: true)
-
使用
AFURLSessionManager
和setDownloadTaskDidWriteDataBlock:
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];