2012-06-25 13 views
12

Pomyślałem, że to wymyśliłem, ale po prostu nie mogę go uruchomić. Mam metodę, która jest wywoływana na każdym adresie URL w tablicy. Ta metoda ma adres URL obrazu, który powinien zostać pobrany w określonej ścieżce w folderze Support Application do użytku w trybie offline. Ale może błędnie interpretuję metody w bibliotece AFNetwork. Moja metoda wygląda następująco:Pobierz plik/obraz za pomocą AFNetworking w systemie 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 jest bezpośredni link do zdjęcia, które chcę, aby pobrać.

Ponieważ ta metoda jest wywoływana dla wszystkich obrazów, wszystkie dzienniki są wywoływane kilka razy i wydają się poprawne.

Odpowiedz

39

Masz tu kilka problemów. więc po pierwsze, dlaczego używasz @autoreleasepool? Myślę, że tutaj nie ma takiej potrzeby. również, czy używasz ARC? Rozważam to, do końca mojej odpowiedzi.

w AFNetworking jest klasa o nazwie AFImageRequestOperation, więc byłby to dobry pomysł do użycia. najpierw zaimportować go

#import "AFImageRequestOperation.h" 

następnie można utworzyć obiekt

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

teraz, w bloku sukcesu, masz UIImage trzeba. tam musisz pobrać katalog dokumentów. Twój kod nie będzie działać na urządzeniu ios.

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

a następnie można użyć NSDatas writeToFile

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

wreszcie, trzeba rozpocząć operację

[operation start]; 

wszystko razem:

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

Ty wskazał mi prosto . Miałem pewne wątpliwości co do tego, co robię, dziękuję bardzo. –

+2

dodatkowe: jeśli masz wiele żądań jednocześnie, rozważ użycie 'NSOperationQueue' (wszystkie klasy AFRequestOperation są zgodne z kodowaniem) i pozwól kolejce obsłużyć operacje. może się to przydać i nie wystrzeli 100 żądań w tym samym czasie. – choise

+0

Ile wniosków może zwykle obsługiwać aplikacja bez implementacji NSOperationQueue ?, to nigdy nie będzie więcej niż 50 żądań, czy to wystarczająco, że warto ją wdrożyć? –

5

Problem polega na tym, że operacja nie zostaje zachowana. Zostanie natychmiast zwolniony.

Wykonaj operację jako właściwość klasy lub pozwól kolejce operacji (także właściwości) obsłużyć żądanie (zalecane). W tym drugim przypadku nie należy wywoływać [operation start]. Podczas korzystania z AFHTTPClient kolejka operacji będzie również zarządzana.

Należy również zarejestrować wywołanie zwrotne zakończenia dla operacji żądania (setCompletionBlockWithSuccess:failure:).

Powiązane problemy