如何在CollectionView iOS中停止自动重新加载和刷新图像

时间:2016-06-22 09:57:48

标签: ios asynchronous uiimageview uicollectionview nsmutableurlrequest

我正在尝试将一些图像从URL显示到我的集合视图中。但是当我尝试这样做时,我的图像会显示在集合视图中,但它们会随机保持刷新和重新加载。此外,当我尝试滚动collectionView时,它再次重新加载我不想要的整个数据。我只想向用户显示预览图像。 下面是我从URL获取图像并将其显示在集合View上的代码。

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];

 __block  NSString *filename;     

for(NSDictionary *item in [jsonSD objectForKey:@"Data"]) {       
      for (int i=0; i<=[[item objectForKey:@"Count"]integerValue]; i++) {
         filename=[NSString stringWithFormat:@"http://..URL../media/content/%@%@%d_1.png",_getstring,[item objectForKey:@"subcategory_id"],i];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{     
              NSURL *url = [NSURL URLWithString:filename];
                  [self downloadImageWithURL:url completionBlock:^(BOOL succeeded, NSData *data) {
                                if (succeeded) {
                                    iv.image = [[UIImage alloc] initWithData:data];                                        
                                }
                                    }];

                      });
    }
  }

return cell;
}

- (void)downloadImageWithURL:(NSURL *)url completionBlock:(void (^)(BOOL succeeded, NSData *data))completionBlock
{
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    if (!error) {
        completionBlock(YES, data);
    } else {
        completionBlock(NO, nil);
    }
}];
}

这里&#39; iv&#39;是我的imageView,我在集合视图的单元格上显示图像。 我尝试搜索相关内容,但我对上述问题没有任何想法。

请帮帮我。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:1)

所以看起来这里有两个问题:

第一个问题是:

cellForItemAtIndexPath

每次在屏幕上出现单元格时都会被调用,这意味着如果您正在滚动,那么每次单元格出现在屏幕上时都会调用downloadImageWithURL

第二个问题似乎是使用for (int i=0; i<=[[item objectForKey:@"Count"]integerValue]; i++)

为每个单元格加载了多个图像

这个循环似乎下载了多个图像,然后依次在同一个单元格上设置它们?

第一期的一些解决方案:

  1. 如果您只需要显示一些项目,请加载viewDidLoad中的所有图像,并在每次下载其中一个图像时更新数据源。
  2. 下载每个单元格的图像后,将其添加到阵列中。每次加载一个单元格时,检查该数组是否包含该单元格的图像并使用该单元格而不是下载新单元格。
  3. 第二个问题:

    不确定循环在这里要实现的目标,您是否希望循环中的每个图像都显示在它自己的集合视图单元格中?

    <强>更新

    这是一个快速示例,向您展示代码的外观。我不知道jsonSD或代码的其他部分包含哪些内容,但它应该给你正确的想法:

    @interface TestCollectionViewController () {
    NSMutableArray *datasource;
    NSDictionary *jsonSD;
    }
    
    
    @end
    
    @implementation TestCollectionViewController
    
    static NSString *const reuseIdentifier = @"Cell";
    
    - (void)viewDidLoad {
    [super viewDidLoad];
    
    // We want to load the data from all cells as soon as the view loads, instead of loading the data as the cells scroll.
    // Lazy loading cells will require a more advanced implementation
    
    [self loadDatasource];
    
    }
    
    - (void)loadDatasource {
    
    for (NSDictionary *item in [jsonSD objectForKey:@"Data"]) {
    
        // Fill the datasource with null objects which match the total number of objects you want to display
    
        datasource = [NSMutableArray arrayWithCapacity:[[item objectForKey:@"Count"] integerValue]];
    
        for (int i = 0; i <= [[item objectForKey:@"Count"] integerValue]; i++) {
    
            [datasource addObject:[NSNull null]];
    
        }
    
        // Reload the collectionview now so that the empty cells will be displayed with no image.
    
        [self.collectionView reloadData];
    
        // Load each image individually and replace the corresponding NSNull in the datasource.
    
        for (int i = 0; i <= [[item objectForKey:@"Count"] integerValue]; i++) {
    
            NSString *filename = [NSString stringWithFormat:@"http://..URL../media/content/%@%@%d_1.png", _getstring, [item objectForKey:@"subcategory_id"], i];
    
            NSURL *url = [NSURL URLWithString:filename];
            [self downloadImageWithURL:url completionBlock:^(BOOL succeeded, NSData *data) {
                if (succeeded) {
    
                    [datasource replaceObjectAtIndex:i withObject:[UIImage imageWithData:data]];
    
                    // Reload the collectionview after each item has downloaded so the image gets displayed in the cell.
    
                    [self.collectionView reloadData];
                }
            }];
    
        }
    }
    }
    
    - (void)downloadImageWithURL:(NSURL *)url completionBlock:(void (^)(BOOL succeeded, NSData *data))completionBlock {
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
        if (!error) {
            completionBlock(YES, data);
        } else {
            completionBlock(NO, nil);
        }
    }];
    }
    
    #pragma mark <UICollectionViewDataSource>
    
    - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    
    // Only displaying one section
    
    return 1;
    }
    
    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return datasource.count;
    }
    
    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
    
    // Configure the cell
    
    if ([datasource objectAtIndex:indexPath.row] == [NSNull null]) {
    
        // Display a default image here
    
    } else {
    
        // Image has been loaded, display it in the imageview
    
        iv.image = [datasource objectAtIndex:indexPath.row];
    }
    
    return cell;
    }
    

    更新2:

    上面的答案效率不高,如果你有数百件物品,效果也不会太好。为了更加可靠的实现,我建议使用像SDWebImage这样的库来为您处理它。然后你可以做一些简单的事情:

    [cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
               placeholderImage:[UIImage imageNamed:@"placeholder.png"]
                      completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {... completion code here ...}];
    

答案 1 :(得分:0)

我不明白你想要做什么,当你滚动你的集合视图时,它总是会获取图像数据,因为重用机制。您可以在viedDidLoad()方法中获取图像数据,在完成获取图像数据后重新加载您的集合视图。