2012-06-25 15 views
12

Pensé que lo había resuelto, pero no puedo hacerlo funcionar. Tengo un método que se llama en cada URL de una matriz. Este método tiene una URL de una imagen que debe descargarse en una ruta específica en una carpeta de soporte de aplicaciones para su uso sin conexión. Pero tal vez estoy malinterpretando los métodos en la biblioteca AFNetwork. Mi método es el siguiente:¿Descargue un archivo/imagen con AFNetworking en iOS?

- (void) downloadImageInBackground:(NSDictionary *)args{ 

    @autoreleasepool { 

    NSString *photourl = [args objectForKey:@"photoUrl"]; 
    NSString *articleID = [args objectForKey:@"articleID"]; 
    NSString *guideName = [args objectForKey:@"guideName"]; 
    NSNumber *totalNumberOfImages = [args objectForKey:@"totalNumberOfImages"]; 

    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:photourl]]; 

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; 
    operation.inputStream = [NSInputStream inputStreamWithURL:[NSURL URLWithString:photourl]]; 

    [operation setShouldExecuteAsBackgroundTaskWithExpirationHandler:^{ 
     DLog(@"PROBLEMS_AF"); 
    }]; 
    DLog(@"URL_PHOTOURL: %@", photourl); 
    DLog(@"indexSet: %@", operation.hasAcceptableStatusCode); 
    [operation response]; 

    NSData *data = [args objectForKey:@"data"]; 

    NSString *path; 
    path = [NSMutableString stringWithFormat:@"%@/Library/Application Support/Guides", NSHomeDirectory()]; 
    path = [path stringByAppendingPathComponent:guideName]; 
    NSString *guidePath = path; 
    path = [path stringByAppendingPathComponent:photourl]; 

    if ([[NSFileManager defaultManager] fileExistsAtPath:guidePath]){ 
     [[NSFileManager defaultManager] createFileAtPath:path 
               contents:data 
               attributes:nil]; 
    } 

    DLog(@"path: %@", path); 
    operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO]; 
    [operation start]; 


    DLog(@"isExecuting: %d",[operation isExecuting]); 
    DLog(@"IS_FINISHED: %d",[operation isFinished]); 


    } 

} 

PhotoURL es el enlace directo a la imagen que quiero descargar.

Como se utiliza este método para todas las imágenes, todos los registros se llaman varias veces y parecen ser correctos.

Respuesta

39

Tiene algunos problemas aquí. así que primero, ¿por qué estás usando @autoreleasepool? Creo que no hay necesidad de esto aquí. también, ¿estás usando ARC? lo considero por el resto de mi respuesta.

en AFNetworking hay una clase llamada AFImageRequestOperation, por lo que esta sería una buena idea para su uso. primero, se importa

#import "AFImageRequestOperation.h" 

entonces se podría crear un objeto

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:photourl]]; 
AFImageRequestOperation *operation; 
operation = [AFImageRequestOperation imageRequestOperationWithRequest:request 
    imageProcessingBlock:nil 
    cacheName:nil 
    success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) { 

    } 
    failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) { 
     NSLog(@"%@", [error localizedDescription]); 
    }]; 

ahora, en el bloque de éxito, tienes el UIImage que necesita. allí necesita obtener el directorio de documentos. su código no funcionará en un dispositivo ios.

// Get dir 
NSString *documentsDirectory = nil; 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
documentsDirectory = [paths objectAtIndex:0]; 
NSString *pathString = [NSString stringWithFormat:@"%@/%@",documentsDirectory, guideName]; 

y entonces se podría utilizar NSDatas writeToFile

// Save Image 
NSData *imageData = UIImageJPEGRepresentation(image, 90); 
[imageData writeToFile:pathString atomically:YES]; 

por fin, lo que necesita para iniciar la operación

[operation start]; 

todos juntos:

- (void)downloadImageInBackground:(NSDictionary *)args{ 

    NSString *guideName = [args objectForKey:@"guideName"]; 
    NSString *photourl = [args objectForKey:@"photoUrl"]; 

    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:photourl]]; 

    AFImageRequestOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:request 
     imageProcessingBlock:nil 
     cacheName:nil 
     success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) { 

      // Get dir 
      NSString *documentsDirectory = nil; 
      NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
      documentsDirectory = [paths objectAtIndex:0]; 
      NSString *pathString = [NSString stringWithFormat:@"%@/%@",documentsDirectory, guideName]; 

      // Save Image 
      NSData *imageData = UIImageJPEGRepresentation(image, 90); 
      [imageData writeToFile:pathString atomically:YES]; 

     } 
     failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) { 
      NSLog(@"%@", [error localizedDescription]); 
     }]; 

    [operation start]; 
} 
+0

Me apuntaba directamente . Tenía algunas dudas sobre lo que estaba haciendo, muchas gracias. –

+2

adicional: si tiene varias solicitudes a la vez, considere el uso de 'NSOperationQueue' (todas las clases de AFRequestOperation son compatibles con la codificación) y deje que la cola maneje las operaciones. esto podría ser útil y no disparará 100 solicitudes al mismo tiempo. – choise

+0

¿Cuántas solicitudes puede manejar una aplicación sin implementar NSOperationQueue ?, nunca serán más de 50 solicitudes, ¿es suficiente que valga la pena implementarla? –

5

El problema aquí es que la operación no se conserva. Será desasignado inmediatamente.

Haga de la operación una propiedad de su clase o permita que una cola de operación (también una propiedad) maneje la solicitud (recomendado). En este último caso, no llame al [operation start]. Cuando usa AFHTTPClient, la cola de operaciones también será administrada por usted.

También debe registrar una devolución de llamada completa para la operación de solicitud (setCompletionBlockWithSuccess:failure:).

Cuestiones relacionadas