【问题标题】:Download images in order with AFNetworking使用 AFNetworking 按顺序下载图像
【发布时间】:2013-04-06 16:11:26
【问题描述】:

如何使用 AFNetworking 按顺序下载图像? “按顺序”指的是按顺序执行success 块。

最初我认为使用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。但是,当请求已经被缓存时,成功块将被乱序处理。我怀疑这是 NSOperation 限制,而不是 AFNetworking。

我错过了什么吗?

【问题讨论】:

    标签: ios afnetworking nsoperation nsoperationqueue


    【解决方案1】:

    作为一种解决方法,我将图像存储在字典中,并在每次请求成功时按顺序处理它们。像这样:

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

    【讨论】:

      【解决方案2】:

      您的解决方案可以正常工作,这是另一种方法:

      对于“完美”的用户体验,您应该并行发出所有操作,并按顺序处理图像(如果不需要,请不要等待)。
      (此处的错误处理方式不同)
      你可以试试这个(未经测试,你可以更好地设计模型[不要只使用这样的数组]):

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-10-30
        • 2014-05-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-26
        • 1970-01-01
        相关资源
        最近更新 更多