2012-06-25 14 views
12

Pensavo di averlo capito ma non riesco a farlo funzionare. Ho un metodo che viene chiamato su ogni URL in un array. Questo metodo ha un URL di un'immagine che deve essere scaricata in un percorso specifico in una cartella Supporto applicazioni per l'utilizzo offline. Ma forse sto interpretando male i metodi nella libreria di AFNetwork. Il mio metodo è simile al seguente:Scaricare un file/immagine con AFNetworking in 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 è il link diretto all'immagine che voglio scaricare.

Poiché questo metodo viene chiamato per tutte le immagini, tutti i registri sono chiamati più volte e sembrano essere corretti.

risposta

39

Hai qualche problema qui. quindi prima, perché stai usando @autoreleasepool? penso che non ci sia bisogno di questo qui. inoltre, stai usando ARC? lo considero, per il resto della mia risposta.

in AFNetworking c'è una classe chiamata AFImageRequestOperation, quindi questa sarebbe una buona idea da usare. In primo luogo, importarlo

#import "AFImageRequestOperation.h" 

allora si potrebbe creare un oggetto

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

ora, nel blocco di successo, avete ottenuto l'UIImage hai bisogno. lì è necessario ottenere la directory dei documenti. il tuo codice non funzionerà su un dispositivo ios.

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

e allora si potrebbe utilizzare NSDatas writeToFile

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

finalmente, è necessario avviare l'operazione

[operation start]; 

tutti insieme:

- (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

Mi hai puntato dritto . Avevo dei dubbi su quello che stavo facendo, grazie mille. –

+2

aggiuntivo: se si hanno più richieste contemporaneamente, considerare l'uso di un 'NSOperationQueue' (tutte le classi AFRequestOperation sono conformi alla codifica) e lasciare che la coda gestisca le operazioni. questo potrebbe rivelarsi utile e non genererà 100 richieste allo stesso tempo. – choise

+0

Quante richieste di solito un'app può gestire senza implementare NSOperationQueue ?, non saranno mai più di 50 richieste, è sufficiente che valga la pena implementarle? –

5

Il problema qui è che l'operazione non viene mantenuta. Sarà deallocato immediatamente.

O rendere l'operazione una proprietà della classe o lasciare che una coda di operazioni (anche una proprietà) gestisca la richiesta (consigliata). In quest'ultimo caso non chiamare [operation start]. Quando si utilizza AFHTTPClient, la coda delle operazioni verrà gestita automaticamente.

Inoltre, è necessario registrare un callback di completamento per l'operazione di richiesta (setCompletionBlockWithSuccess:failure:).

Problemi correlati