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

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

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总是设置为零。 我为此提出了一个问题。

我也尝试在管理器上调用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:方法( AFHTTPSessionManager继承)来设置用于接收下载进度更新的块。

[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实施遭到严重破坏。 我建议使用类似MAKVONotificationCenter中由Mike Ash提出的更好的实现。 如果您有兴趣了解为什么苹果的KVO被破坏,请阅读Mike Ash的Key-Value Observing Done Right。


我遇到了类似的问题,并找到了解决方案。

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

#import <AFNetworking/UIKit+AFNetworking.h>

并使用可用于UIProgressView的附加方法

setProgressWithDownloadProgressOfTask:动画:

我是如何做到的:

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的简单解决方案:

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
        })

现在你有两个选择:

  • 使用UIProgressViewsetProgressWithDownloadProgressOfTask:

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

    sessionManager.setDownloadTaskDidWriteDataBlock { session, sessionDownloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite in
    
        let progress = Float(totalBytesWritten)/Float(totalBytesExpectedToWrite)
            //do sth with current progress
    }
    
  • 最后不要忘记:

    sessionDownloadTask.resume()
    
    链接地址: http://www.djcxy.com/p/96767.html

    上一篇: How to get download progress in AFNetworking 2.0?

    下一篇: How to download uiimage async