使用AFNetworking 2.0 + NSProgress + Custom ProgressView获取下载进度

时间:2014-01-27 13:17:57

标签: ios iphone objective-c ios7 afnetworking-2

我对使用AFNetworking 2.0的下载任务取得进展感到困惑。我创建了一个单例对象,我集中了我的下载操作(我的应用程序将下载播客文件)。

所以,我有一个使用此方法的PodcastManager类,我也使用我创建的Podcast对象:

- (void)downloadPodcast:(Podcast *)podcast completion:(CompletionBlock)completionBlock{

podcast.downloadState = DOWNLOADING;

NSURL *url = [NSURL URLWithString:podcast.enclosure];
NSURLRequest *request = [NSURLRequest requestWithURL:url];

NSProgress *progress = [NSProgress progressWithTotalUnitCount:podcast.size];

NSURLSessionDownloadTask *downloadTask = [self.downloadManager downloadTaskWithRequest:request progress:&progress destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {

NSURL *documentsDirectoryPath = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]];
  //Return final path for podcast file

} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
if (!error) {
  //Handle success 
}
else{
  //Handle errors
}
}];


[progress addObserver:self forKeyPath:@"fractionCompleted" options:NSKeyValueObservingOptionNew context:nil];

[downloadTask resume];

 if (completionBlock) {
    dispatch_async(dispatch_get_main_queue(), ^{
     completionBlock();
   });
 } 
}

目前,出于调试目的,我也在PodcastManager

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
  if ([keyPath isEqualToString:@"fractionCompleted"] && [object isKindOfClass:[NSProgress class]]) {
    NSProgress *progress = (NSProgress *)object;
    NSLog(@"Download at %f", progress.fractionCompleted);
  }
}

我从UITableViewController调用downloadPodcast:completion:方法,其中每个单元代表一个Podcast。我正在尝试做的是在单元格中显示自定义进度视图以及该播客的下载进度。

我知道AFNetworking 2.0有一个很棒的UIProgressView可以轻松获得下载任务的进度,但在我的应用程序中我正在使用这个自定义进度视图https://github.com/danielamitay/DACircularProgress所以我无法使用此功能:(

任何人都可以告诉我这样做的方法吗? 感谢

更新:嗯,我在这个问题上取得了一些进展。现在,我可以使用KVO从我的自定义单元格访问下载进度。使用AFURLSessionManager setDownloadTaskDidWriteDataBlock中的方法,我得到当前下载的百分比,并将其保存在单元格的属性中。

[[manager downloadManager] setDownloadTaskDidWriteDataBlock:^(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {

  self.downloadPercentage = (float)totalBytesWritten/(float)totalBytesExpectedToWrite;
}];

然后用KVO我查看我的财产

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
  if ([keyPath isEqualToString:@"downloadPercentage"] && [object isKindOfClass:[FDSEpisodeCell class]]) {
    int percentage = self.downloadPercentage * 100;

    NSLog(@"Percentage %d", percentage);

    [self.downloadLabel setText:[NSString stringWithFormat:@"%d",percentage]];

 }
}

我现在的问题是我试图在单元格内的UILabel中显示这个百分比,但是虽然我更改了标签文本但没有任何变化。如何刷新标签以显示当前百分比?我试图使用setNeedsDisplay但没有发生任何事情。如果我使用TableView中的reloadData,会发生奇怪的事情并且视图变成空白。

另外,我尝试使用NSTimer,但都没有用。

2 个答案:

答案 0 :(得分:11)

使用AFURLConnectionOperation -setDownloadProgressBlock :,每次调用块时,以totalBytesRead与totalBytesExpectedToRead的比率更新进度。

要更新UI元素,只需通过主线程调用更新:

dispatch_async(dispatch_get_main_queue(), ^(void){
    //Run UI Updates
});

答案 1 :(得分:1)

Swift的简单解决方案:

let progressView: UIProgressView?
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)

sessionDownloadTask.resume()