0

我在这一整个下午,我无法想象它,所以你的帮助会很棒!我有一个自定义的UICollectionViewCell,里面填充了我在飞行中创建的图像。图像的路径存储在分析和查询完成后,我打电话[self.collectionView reloadData].如何正确加载自定义UICollectionViewCell上的图像?

在我cellForItemAtIndexPath我有以下代码:

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

MovieCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath]; 
// Configure the cell 
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"original_title" ascending:YES]; 
[self.moviesforWatchlist sortUsingDescriptors:[NSArray arrayWithObjects:sort, nil]]; 
cell.userInteractionEnabled = YES; 
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; 
[cell addSubview:spinner]; 

NSDictionary *movie = self.moviesforWatchlist[indexPath.row]; 
NSString *moviePosterPath = movie[@"poster_path"]; 
NSString *posterURL = [NSString stringWithFormat:@"http://image.tmdb.org/t/p/w342%@", moviePosterPath]; 
NSURL *posterImage = [NSURL URLWithString:posterURL]; 
UIImage *cachedImage = [self.imageCache objectForKey:posterImage]; 

if (cachedImage) { 
    cell.imageView.image = cachedImage; 
} 
else if (cell.imageView.image == nil) { 
    cell.imageView.image = [UIImage imageNamed:@"default_collectionviewcell.jpeg"]; 
    dispatch_queue_t downloadQueue = dispatch_queue_create("get image data", NULL); 
    dispatch_async(downloadQueue, ^{ 
     [spinner startAnimating]; 
     NSData *imageData = [NSData dataWithContentsOfURL:posterImage]; 
     UIImage *image = [UIImage imageWithData:imageData]; 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [spinner stopAnimating]; 
      MovieCollectionViewCell *updateCell = (id)[collectionView cellForItemAtIndexPath:indexPath]; 
      if (updateCell) { 
       updateCell.imageView.image = image; 
       [updateCell reloadInputViews]; 
       [self.collectionView reloadItemsAtIndexPaths:[self.collectionView indexPathsForVisibleItems]]; 
     } 
     }); 
     [self.imageCache setObject:image forKey:posterImage]; 
    }); 
    } 
[self.collectionView reloadItemsAtIndexPaths:[self.collectionView indexPathsForVisibleItems]]; 
return cell; 
} 

我打电话这样的查询方法:

-(void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
    [self getWatchlistData]; 
    [self.collectionView reloadData]; 
} 

这会导致图像闪烁,直到图像加载到UICollectionViewCells。我希望显示在我的collectionviewcell中的图像按照字母顺序排列,因此我正在排序包含路径的阵列,在cellforitemsatindexpath这是什么导致图像闪烁?或者是别的什么?非常感谢您的帮助!

回答

-1

尝试使用DLImageLoader

[[DLImageLoader sharedInstance] displayImageFromUrl:@"image_url_here" 
             imageView:@"UIImageView here"]; 

[[DLImageLoader sharedInstance] loadImageFromUrl:@"image_url_here" 
            completed:^(NSError *error, UIImage *image) { 
             if (error == nil) { 
              // if we have no any errors 
             } else { 
              // if we got an error when load an image 
             } 
            }]; 
0

有许多事情我会改变:

  1. 我不会排序您在cellForItemsAtIndexPAth阵列。当每个单元格都显示在屏幕上时,会调用该方法,所以如果没有必要,您可能会多次使用它。如果您的数据在正在创建的单元格与下一个单元格之间发生变化,那么重新排序可能会混淆collectionView indexPath.row与您的数组索引之间的链接。我将在数组填充时对数组进行排序,可能在您的viewWillAppeargetWatchlistData方法中。如果在此之后数据确实发生了变化,请使用其他一些collectionView委托/数据源方法来处理插入/删除/移动。但我不认为这是造成图像闪烁的原因。

  2. 在回发到主队列的代码中,您调用cellForItemAtIndexPath方法,更新单元格图像并调用reloadInputViews(这可能会以某种方式重新配置单元格)。但是,您可以拨打reloadItemsAtIndexPaths查看所有可见的单元格。这样做会导致您的collectionView重新调用每个可见项目的数据源方法,导致每个图片都从缓存中重新加载。我认为这是你闪烁的原因。我只是将下载的图像保存到缓存中,然后只需调用reloadItemsAtIndexPaths就可以找到一个受影响的indexPath。将调用cellForRowAtIndexPath数据源方法,并将从缓存中恢复图像并将其添加到新单元中。

  3. 同样,我认为cellForItemAtIndexPath末尾的reloadItemsAtIndexPaths是多余的,可能会导致闪烁。

  4. 我认为你有一些细胞再利用问题的风险 - 例如,你将微调器添加到每个细胞。但是出队的单元格可能之前已经显示过,因此已经有一个微调框(尽管已停止,因此可能已隐藏)。如果你来回滚动很多,你最终可能会得到一些装有纺纱器的细胞,浪费记忆。在将它添加为子视图之前,我会给微调器一个标签,然后使用viewWithTag来确定是否已将微调器添加到已出队的单元格中(如果是,请将其删除)。如有必要,只能添加微调器(即在您的if ...image == nil子句中)。

  5. 也许不太可能,但是如果出列的单元格有一个默认图像(因此cell.imageView.image!= nil)并且正在被重用于图像尚未被缓存的单元格(所以cachedImage == nil ),那么你的调度方法都不会被执行,所以图像将永远不会被下载。

对不起,如果这有点重,但我希望它是有用的。

+0

不用担心!我非常感谢你的反馈。我刚开始学习Objective-C,iOS开发和编程,所以这些答案很棒。我知道我做错了什么,但是让它正常工作仍然取决于我。 关于这个......我认为它现在正在工作!我在对数组进行排序时,它在getWatchListData方法中填充(这似乎有很大的不同)。基本上,我做了所有的建议。唯一的问题是,在第一次加载时,有时单元格会填充错误的图像。任何想法如何我可以解决这个问题? – bienj0 2014-10-18 10:56:04

+0

只有几个指针:首先,检查您的缓存是否正确填充。它可能在之前的运行中被错误填充,即使您的代码现在可能没问题。其次,注意细胞再利用问题,特别是如果您在滚动列表时看到相同的图像出现。我发现NSLog和断点对于追踪这类问题确实很有帮助。 – pbasdf 2014-10-18 22:48:24

0

我有同样的问题,当任何图像下载然后它轻弹视图。我之前喜欢重新加载那个单元格,所以它会调用一些collectionview的委托方法。所以我删除它,并为重新加载单元格单独的方法。现在当任何新的图像重新加载,然后我调用这个方法,而不是reloadCellForIndexPath :.在自定义方法中,只需从您的cellForItemAtIndexPath:复制粘贴代码即可。在自定义方法中分配单元格。 CollectionPhotoItem cell =(CollectionPhotoItem)[self.collection cellForItemAtIndexPath:indexPath];

就是这样。它会显示您的手机没有任何轻拂。谢谢。

相关问题