ios 如何在 AFNetworking 2.0 中获取下载进度?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19145093/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 01:59:14  来源:igfitidea点击:

How to get download progress in AFNetworking 2.0?

iosobjective-cafnetworking-2

提问by gregschlom

I am using AFURLSessionManager to create a new download task:

我正在使用 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];

The file gets downloaded fine, however, how do I get progress notifications?

该文件可以正常下载,但是,我如何获得进度通知?

pis always set to nil. I've filed an issuefor that.

p始终设置为零。我已经为此提出了一个问题

I've also tried to call setDownloadTaskDidWriteDataBlockon the manager, and I do get progress notifications there but I receive them all grouped together afterthe file has been downloaded.

我也试过打电话setDownloadTaskDidWriteDataBlock给经理,我确实在那里收到了进度通知,但在下载文件我将它们全部组合在一起。

Seems like this area is still a bit buggy in AFNetworking 2.0

似乎这个区域在 AFNetworking 2.0 中仍然有点问题

Any ideas?

有任何想法吗?

回答by Sendoa

You should observe the fractionCompletedproperty of your NSProgressobject using KVO:

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

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];

Then add the observer method:

然后添加观察者方法:

- (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];
    }
}

Of course, you should check keyPathand/or objectparameters to decide if that's the object/property you want to observe.

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

You can also use the setDownloadTaskDidWriteDataBlock:method from AFURLSessionManager(from which AFHTTPSessionManagerinherits) to set a block for receiving download progress updates.

您还可以使用setDownloadTaskDidWriteDataBlock:from AFURLSessionManager(from which AFHTTPSessionManagerinherits) 方法设置接收下载进度更新的块。

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

This AFNetworking method maps the URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:method from NSURLSessionDownloadDelegateprotocol to a more convenient block mechanism.

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

BTW, Apple's KVO implementation is severely broken. I recommend using a better implementation like the one proposed by Mike Ash with MAKVONotificationCenter. If you are interested in reading why Apple's KVO is broken, read Key-Value Observing Done Rightby Mike Ash.

顺便说一句,Apple 的 KVO 实现被严重破坏。我建议使用更好的实现,例如 Mike Ash 与MAKVONotificationCenter提出的实现。如果您有兴趣阅读 Apple 的 KVO 被破坏的原因,请阅读Mike Ash 的Key-Value Observing Done Right

回答by CKD

I faced a similar problem, and found a solution.

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

Check the link below: http://cocoadocs.org/docsets/AFNetworking/2.0.1/Categories/UIProgressView+AFNetworking.html

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

#import <AFNetworking/UIKit+AFNetworking.h>

and use the additional method available to your UIProgressView

并使用可用于 UIProgressView 的其他方法

setProgressWithDownloadProgressOfTask:animated:

setProgressWithDownloadProgressOfTask: 动画:

How I did it:

我是如何做到的:

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];

回答by Bart?omiej Semańczyk

Simple solutions for Swift:

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

Now you have 2 options:

现在您有 2 个选择:

  1. Using UIProgressViewand setProgressWithDownloadProgressOfTask:

    progressView.setProgressWithDownloadProgressOfTask(sessionDownloadTask, animated: true)
    
  2. Using AFURLSessionManagerand setDownloadTaskDidWriteDataBlock:

    sessionManager.setDownloadTaskDidWriteDataBlock { session, sessionDownloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite in
    
        let progress = Float(totalBytesWritten)/Float(totalBytesExpectedToWrite)
            //do sth with current progress
    }
    
  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
    }
    

At the end do not forget about:

最后不要忘记:

sessionDownloadTask.resume()

回答by DURGESH

For Download file with progress status use this code

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

 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];