我整个下午都在这,我无法理解,所以你的帮助会很棒!我有一个自定义的UICollectionViewCell,我正在填充我即时创建的图像。图像的路径存储在Parse中,查询完成后,我调用[self.collectionView reloadData].
在我的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
这是什么导致图像闪烁?或者是别的什么?非常感谢您的帮助!
答案 0 :(得分:0)
我会改变一些事情:
我不会在cellForItemsAtIndexPAth
中对您的数组进行排序。当每个单元格显示在屏幕上时调用该方法,因此当不需要时,您可能会多次使用它。如果您的数据在创建的单元格和下一个单元格之间发生变化,那么重新排序可能会破坏collectionView indexPath.row
和您的数组索引之间的链接。我会在填充数组时对其进行排序,可能是在viewWillAppear
或getWatchlistData
方法中。如果此后数据发生了变化,请使用其他一些collectionView委托/数据源方法来处理插入/删除/移动。但我不认为这会导致图像闪烁。
在您回发到主队列的代码中,您调用cellForItemAtIndexPath
方法,更新单元格图像并调用reloadInputViews
(可能以某种方式重新配置单元格)。但是,然后您为所有可见单元格调用reloadItemsAtIndexPaths
。这样做会导致collectionView为每个可见项重新调用cellForItemAtIndexPath
数据源方法,从而导致从缓存中重新加载每个图像。我认为这是你闪烁的原因。我只是将下载的图像保存到缓存中,然后仅针对受影响的一个indexPath调用reloadItemsAtIndexPaths
。将调用cellForRowAtIndexPath
数据源方法,并将从缓存中恢复图像并将其添加到新单元格。
同样,我认为reloadItemsAtIndexPaths
末尾的cellForItemAtIndexPath
是多余的,可能会导致闪烁。
我认为您有一些细胞重用问题的风险 - 例如,您将微调器添加到每个细胞。但是出列的细胞可能已经显示过,因此已经有了一个微调器(尽管已停止,因此可能已隐藏)。如果你来回滚动很多,你最终可能会遇到带有大量微调器的单元,浪费内存。在将它作为子视图添加之前,我会给微调器一个标签,然后使用viewWithTag
来确定是否已经将一个微调器添加到出队的单元格中(如果是这样,将其删除)。并且只在必要时添加微调器(即在if ...image == nil
子句中)。
也许不太可能,但是如果出列的单元格有一个默认图像(所以cell.imageView.image!= nil)并且正在被重用于尚未缓存图像的单元格(所以cachedImage == nil),那么你的调度方法都不会被执行,所以永远不会下载图像。
对不起,如果那有点重,但我希望它有用。
答案 1 :(得分:0)
我有同样的问题,当任何图像下载后,它会轻弹视图。我之前要重新加载那个单元格,所以它会调用collectionview的一些委托方法。所以我删除它并为重载单元格制作单独的方法。现在当任何新图像重新加载时,我调用此方法而不是reloadCellForIndexPath:。在自定义方法中,只需从您的cellForItemAtIndexPath:复制粘贴代码。在自定义方法中分配单元格 CollectionPhotoItem cell =(CollectionPhotoItem )[self.collection cellForItemAtIndexPath:indexPath];
就是这样。它将显示你的细胞没有任何电影。感谢。
答案 2 :(得分:-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
}
}];