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

Posted

技术标签:

【中文标题】如何在 CollectionView iOS 中停止自动重新加载和刷新图像【英文标题】:How to stop Automatic reloading and refreshing of images in CollectionView iOS 【发布时间】:2016-06-22 09:57:48 【问题描述】:

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

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

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

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

【问题讨论】:

【参考方案1】:

看来这里有两个问题:

第一个问题是:

cellForItemAtIndexPath

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

第二个问题似乎是使用for (int i=0; i&lt;=[[item objectForKey:@"Count"]integerValue]; i++) 为每个单元格加载多个图像

这个循环好像是下载多张图片,然后依次设置在同一个单元格上?

第一个问题的一些解决方案:

    如果您只需要显示几个项目,请加载 viewDidLoad 中的所有图像,并在每次下载其中一个图像时更新数据源。 下载每个单元格的图像后,将其添加到数组中。每次加载单元格时,检查数组是否包含该单元格的图像并使用它而不是下载新的。

到第二个问题:

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

更新:

下面是一个简单的示例,向您展示代码的外观。我不知道 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 ...];

【讨论】:

你看对了。我不想在一个单元格中显示所有图像。我想要单个单元格的单个图像。 你能帮帮我吗? 我已经更新了我的答案,建议您可以使用一个库。它应该为你处理所有的缓存。 这有助于解决您的问题吗?如果可以,你能接受我的回答吗,谢谢。 是的。它做了。但是当我尝试滚动集合视图时,它会自动重新加载其中的数据。如何解决这个问题?【参考方案2】:

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

【讨论】:

以上是关于如何在 CollectionView iOS 中停止自动重新加载和刷新图像的主要内容,如果未能解决你的问题,请参考以下文章

当collectionView滚动时,如何使iOS collectionView的特定单元格淡出?

iOS:在 Swift3 中,在 UICollectionViewLayout 部分,我如何访问主要的 CollectionView 属性?

如何在ios中的特定collectionview单元格上应用手势识别器

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

如何在 swift ios 的自定义 collectionView 单元中将字符串值显示到多个标签?

iOS如何知道使用自定义委托按下哪个按钮CollectionView