¿Cómo obtener el progreso de la descarga en AFNetworking 2.0?

Estoy usando AFURLSessionManager para crear una nueva tarea de descarga:

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

El archivo se descarga bien, sin embargo, ¿cómo obtengo las notificaciones de progreso?

p siempre se establece en nil. He archivado un problema para eso.

También traté de llamar a setDownloadTaskDidWriteDataBlock en el administrador, y recibo notificaciones de progreso allí, pero los recibo todos agrupados después de que se haya descargado el archivo.

Parece que esta área todavía tiene problemas en AFNetworking 2.0

¿Algunas ideas?

Debe observar la propiedad fractionCompleted de su objeto NSProgress utilizando KVO:

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

Luego agrega el método del observador:

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

Por supuesto, debe verificar keyPath y / o los parámetros del object para decidir si ese es el objeto / propiedad que desea observar.

También puede usar el método setDownloadTaskDidWriteDataBlock: from AFURLSessionManager (del cual AFHTTPSessionManager hereda) para establecer un bloque para recibir actualizaciones de progreso de descarga.

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

Este método AFNetworking asigna el URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite: del protocolo NSURLSessionDownloadDelegate a un mecanismo de bloque más conveniente.

Por cierto, la implementación de KVO de Apple está severamente rota. Recomiendo usar una mejor implementación como la propuesta por Mike Ash con MAKVONotificationCenter . Si está interesado en leer por qué el KVO de Apple está roto, lea Observación de valores-clave realizada correctamente por Mike Ash.

Enfrenté un problema similar y encontré una solución.

Consulte el siguiente enlace: http://cocoadocs.org/docsets/AFNetworking/2.0.1/Categories/UIProgressView+AFNetworking.html

 #import  

y use el método adicional disponible para su UIProgressView

setProgressWithDownloadProgressOfTask: animado:

Cómo lo hice:

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

Soluciones simples para 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 }) 

Ahora tienes 2 opciones:

  1. Usando UIProgressView y setProgressWithDownloadProgressOfTask:

     progressView.setProgressWithDownloadProgressOfTask(sessionDownloadTask, animated: true) 
  2. Usando AFURLSessionManager y setDownloadTaskDidWriteDataBlock:

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

Al final, no te olvides de:

 sessionDownloadTask.resume() 

Para descargar el archivo con estado de progreso use este código

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