2013-04-06 4 views
0

AFNetworking을 사용하여 이미지를 어떻게 다운로드합니까? "순서대로", 나는 또한 success 블록을 순서대로 실행하는 것을 의미합니다.AFNetworking을 사용하여 순서대로 이미지 다운로드

처음에는 NSOperationQueue을 사용하고 각각 AFImageRequestOperation을 다음 종속성으로 설정하는 것으로 충분하다고 생각했습니다. 이렇게하면 :

- (void) downloadImages 
{ 
    { // Reset 
     [_downloadQueue cancelAllOperations]; 
     _downloadQueue = [[NSOperationQueue alloc] init]; 
     _images = [NSMutableArray array]; 
    } 
    AFImageRequestOperation *previousOperation = nil; 
    for (NSInteger i = 0; i < _imageURLs.count; i++) { 
     NSURL *URL = [_imageURLs objectAtIndex:i]; 
     NSURLRequest *request = [NSURLRequest requestWithURL:URL]; 
     AFImageRequestOperation *operation = [AFImageRequestOperation 
               imageRequestOperationWithRequest:request 
               imageProcessingBlock:nil 
     success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) { 
      [_images addObject:image]; 
      NSLog(@"%d", i); 
     } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {}]; 

     if (previousOperation) { 
      [operation addDependency:previousOperation]; 
     } 
     previousOperation = operation; 

     [_downloadQueue addOperation:operation]; 
    } 
} 

이미지를 다운로드 할 때 i이 순서대로 인쇄됩니다. 그러나 요청이 이미 캐시 된 경우 성공 블록은 순서가 잘못 처리됩니다. AFNetworking이 아닌 NSOperation 제한으로 판단됩니다.

내가 누락 된 항목이 있습니까?

답변

0

해결 방법으로 이미지를 사전에 저장하고 요청이 성공할 때마다 순서대로 처리합니다. 이와 같이 :

- (void) downloadImages 
{ 
    { // Reset 
     [_downloadQueue cancelAllOperations]; 
     _downloadQueue = [[NSOperationQueue alloc] init]; 
     _images = [NSMutableArray array]; 
     _imageDictionary = [NSMutableDictionary dictionary]; 
    } 
    AFImageRequestOperation *previousOperation = nil; 
    for (NSInteger i = 0; i < _imageURLs.count; i++) { 
     NSURL *URL = [_imageURLs objectAtIndex:i]; 
     NSURLRequest *request = [NSURLRequest requestWithURL:URL]; 
     AFImageRequestOperation *operation = [AFImageRequestOperation 
               imageRequestOperationWithRequest:request 
               imageProcessingBlock:nil 
     success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) { 
      [_imageDictionary setObject:image forKey:@(i)]; 
      [self processImages]; 
     } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {}]; 

     if (previousOperation) { 
      [operation addDependency:previousOperation]; 
     } 
     previousOperation = operation; 

     [_downloadQueue addOperation:operation]; 
    } 
} 

- (void) processImages 
{ 
    for (NSInteger i = _images.count; i < _imageURLs.count; i++) { 
     UIImage *image = [_imageDictionary objectForKey:@(i)]; 
     if (!image) break; 
     [_images addObject:image]; 
     NSLog(@"%d", i); 
    } 
} 

이렇게하면 항상 i이 인쇄됩니다.

0

귀하의 솔루션은 잘 작동합니다, 여기에 그것을 할 수있는 또 다른 방법입니다은 "완벽한"그들이 와서 당신이 순서에 따라 병렬 및 프로세스 이미지에서 모든 작업을 실행해야합니다 UX (기다리지 않는다 들어

당신 돈 경우 '할 필요가 없다').

당신이 시도해 볼 수도 있습니다 (오류 처리 다르게 여기 완료) (검증되지 않은, 당신은 더 나은 모델 [바로이 같은 배열을 사용하지 않는] 디자인 할 수 있습니다) :

- (void) processImage:(UIImage*)image 
{ 
    //do something with the image or just [_images addObject:image] 
} 

- (void) downloadImages 
{ 
    { // Reset 
     [_downloadQueue cancelAllOperations]; 
     _downloadQueue = [[NSOperationQueue alloc] init]; 
    } 

    __block NSMutableArray* queue = [[NSMutableArray alloc] initWithCapacity:[_imageURLs count]]; 

    for (NSURL* url in _imageURLs) { 
     __block NSLock* lock = [[NSLock alloc] init]; 
     __block NSMutableArray* container = [NSMutableArray new]; 
     [lock lock]; 
     [queue addObject:@[lock,container,url]]; 
     NSURLRequest *request = [NSURLRequest requestWithURL:url]; 
     void(^compBlock)(NSURLRequest *request, 
         NSHTTPURLResponse *response, 
         UIImage *image) = ^(NSURLRequest *request, 
              NSHTTPURLResponse *response, 
              UIImage *image) 
     { 
      [container addObject:image]; 
      [lock unlock]; 
     }; 
     NSOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:request 
                     imageProcessingBlock:nil 
                        success:compBlock 
                        failure:compBlock]; 
     [_downloadQueue addOperation:operation]; 
    } 

    __block __weak id weakSelf = self; 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     for (NSArray* arr in queue) { 
      NSLock* lock = arr[0]; 
      [lock lock]; 
      NSMutableArray* container = arr[1]; 
      if ([container count]) { 
       [weakSelf processImage:container[0]]; //might want to call this on main thread 
      } else { 
       //error on url = arr[2] 
      } 
      [lock unlock]; 
     } 
    });  
}