【问题标题】:Collection view images are flickering while scrolling收藏视图图像在滚动时闪烁
【发布时间】:2016-06-07 04:24:12
【问题描述】:

我使用下面的代码用图像填充集合视图单元格。

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *identifier = @"Cell";

    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];

    UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
    recipeImageView.image = nil;
    if ([imageArray count] >0){

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
            NSData *data0 = [NSData dataWithContentsOfURL: [NSURL URLWithString:[imageArray objectAtIndex:indexPath.row]]];
            UIImage *image = [UIImage imageWithData: data0];

            dispatch_sync(dispatch_get_main_queue(), ^(void) {
                recipeImageView.image = image;
            });
        });

    }

    [spinnerShow stopAnimating];


    return cell;
}

问题是,当我滚动图像时,图像会闪烁并闪烁。为什么呢?如何使这些图像稳定而不闪烁?

【问题讨论】:

  • 在模拟器上看到了吗?如果是,请确保您通过按 command+1 以全尺寸查看模拟器。
  • 您是否覆盖了包含集合视图的视图控制器中的任何滚动视图方法?
  • 因为单元格是重复使用的,并且您每次都下载所以它会轻弹。下载后将其放入文档目录并在下载之前检查文档目录中是否可用,然后从那里使用它,

标签: ios objective-c uicollectionview


【解决方案1】:

只是一个简短的概述,所以你得到你的答案

UICollectionView 高度优化,因此只在内存中保留屏幕上可见的行。现在,所有行 Cell 都缓存在 Pool 中并被重用而不是重新生成。每当用户滚动 UICollectionView 时,它会将刚刚隐藏的行添加到 Pool 中,并将它们重用于下一个可见行。

那么,现在来回答你的问题

当您滚动 CollectionView 时,collectionView 数据源方法会为每个 indexPath 再次调用,进入可见范围并再次下载您的图像

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

解决方案

在方法之外实例化一个实例 NSMutableDictionary。

现在在您的代码中

@implementation ClassName{
  NSMutableDictionary *cachedImage;
}

-(void)viewDidLoad(){
  [super viewDidLoad];
  cachedImage = [NSMutableDictionary new];
}

/*OLD CODE*/
UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
    recipeImageView.image = nil;
 
    if ([imageArray count] >0){

       //IF image is already downloaded, simply use it and don't download it.
       if(cachedImage[[imageArray objectAtIndex:indexPath.row]] != nil){
           recipeImageView.image = cachedImage[[imageArray objectAtIndex:indexPath.row]];
       }
       else{
           dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
               NSData *data0 = [NSData dataWithContentsOfURL: [NSURL URLWithString:[imageArray objectAtIndex:indexPath.row]]];
               UIImage *image = [UIImage imageWithData: data0];

               dispatch_sync(dispatch_get_main_queue(), ^(void) {
                   recipeImageView.image = image;
                   //****SAVE YOUR DOWNLOADED IMAGE 
                   cachedImage[[imageArray objectAtIndex:indexPath.row]] = image; //****SAVE YOUR DOWNLOADED IMAGE 
               });
           });
       }
}        
/*OLD CODE*/

【讨论】:

  • Im gettting an error expected method to read dictionary not found on object of type of nsmutablearray
  • 是的,我在那里犯了一个错误。它是 NSMutableDictionary,更新了我的答案
  • @gunjotsingh ,仅出于知识目的,我认为如果尝试将图像存储在 NSDictionary 或 NSArray 中,可能会出现内存问题。
  • 有什么方法可以优化吗?
  • 有时在滚动时显示空白图像
【解决方案2】:

据我所知,您正在获取图像但没有缓存它,这就是为什么当您的 UICollectionViewCell 重新加载时,您会获得 UIImageView 的新实例,所以这件事会在您的代码中不断发生......

在这种情况下,我建议您使用 SDWebImageAFNetworking 框架。因为这些框架用简单的代码行(SDWebImage 框架)为您完成了所有棘手的工作,

NSURL* url = [NSURL URLWithString:str];
[yourImageView setBackgroundImageWithURL:url forState:UIControlStateNormal placeholderImage:kPlaceholder];

【讨论】:

  • 不使用第三方库有没有办法解决
  • @KaruppuMGR ,当然,您必须将下载的图像存储到缓存中。只需检查此已接受的答案,它有详细的答案。 stackoverflow.com/questions/11511548/…
猜你喜欢
  • 1970-01-01
  • 2020-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-11
相关资源
最近更新 更多