UICollectionView在滚动时重新加载错误的图像
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UICollectionView在滚动时重新加载错误的图像相关的知识,希望对你有一定的参考价值。
在下面的代码中,我从文本文件下载图像URL,将其存储在NSMutableArray中,然后从CellforItemAtIndexPath中的这些URL下载图像。但是,当我向上和向下滚动片刻时,错误的图像位于错误的位置。它纠正了一秒钟,但我想摆脱滚动问题。这是代码:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = @"Cell2";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
AsyncImageView *recipeImageView = (AsyncImageView *)[cell viewWithTag:100];
UILabel *titleView = (UILabel *)[cell viewWithTag:101];
titleView.numberOfLines = 3;
UIImageView *overlay = (UIImageView *)[cell viewWithTag:111];
FXBlurView *blurView = (FXBlurView *)[cell viewWithTag:110];
blurView.tintColor = [UIColor colorWithRed:51.0 green:51.0 blue:51.0 alpha:1];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
hi = [self videoTitle];
images = [self firstPhoto];
// switch to a background thread and perform your expensive operation
// switch back to the main thread to update your UI
dispatch_async(dispatch_get_main_queue(), ^{
NSString *imgSrc;
NSString *url = images[indexPath.row];
imgSrc = url;
if (imgSrc != nil && [imgSrc length] != 0 ) {
[recipeImageView setImageWithURL:[NSURL URLWithString:images[indexPath.row]] placeholderImage:[UIImage imageNamed:@"red.png"]];
}
else {
NSLog(@"noimage");
recipeImageView.image = [UIImage imageNamed:@"red.png"];
}
titleView.text = hi[indexPath.row];
});
});
return cell;
// recipeImageView.image = [UIImage imageNamed:[videoList objectAtIndex:indexPath.row]];
}
有任何想法吗?谢谢。
我注意到一堆没有评论的downvotes,在再次阅读我的答案后,我猜原来接受的答案(在线下)可能会更好。
这些问题还有一些问题。 UITableView只创建足够的UITableViewCells来显示视图中的每个单元格以及将滚动到视图中的内容。其他单元格在滚出视图后将重新使用。
这意味着当您快速滚动时,单元格会多次设置以获取图像异步,然后显示它,因为获取图像非常慢。图像加载后,它将显示在最初调用以获取它的单元格上,但该单元格可能已经重新使用。
现在我有一个bufferedImage:UIImage?我用作UITableViewCells数据的任何数据类的属性。这最初总是为零,所以我获取图像异步,当dispatch_async返回时它会将它存储在那里,所以下次我需要显示这个单元格它已经准备就绪,如果它仍然是同一个单元格,我也会在单元格中显示它。
所以正确的方法是:
- 开始使用数据对象配置单元格
- 将数据对象存储在单元格中,以便稍后引用
- 检查数据对象是否已经在bufferedImage中设置了图像,如果是,则显示它,就是这样
- 如果还没有图像,请将当前图像重置为空或占位符,然后开始在后台下载图像
- 当异步调用返回时,将图像存储在bufferedImage属性中
- 检查当前单元格中存储的对象是否仍然是您为该图像获取的对象(这非常重要),如果不是,则不执行任何操作
- 如果您仍在同一单元格中显示图像
因此,您在异步调用中传递了一个对象,以便存储所获取的图像。还有另一个对象可以在当前单元格中进行比较。通常,在获取图像之前,单元格已经被重用,因此在下载图像时这些对象会有所不同。
滚动和旋转CollectionViews总是有点问题。我总是有同样的问题,图像出现在错误的单元格中。对于集合视图,会进行某种优化,这会影响图像,但不会影响标签。对我来说这是一个错误但在三个ios版本之后仍然没有解决。
您需要实现以下内容:
这应该总是返回YES基本上总是刷新它。如果这可以解决您的问题,那么您可能会考虑不执行整个重绘,因为它对性能有害。我个人花了很多时间来计算一个屏幕已经通过或线路已经过去等等,但它变得很吵,所以我最后只回到YES。因人而异。
我不确定AsyncImageView
是什么,所以首先让我回答你的问题,好像它是一个UIImageView
:
在你的回调块中(当你回到主队列时),你指的是recipeImageView
。但是,如果用户在下载期间滚动,则cell
对象已被重用。
一旦你进行了回调,就必须假设所有对视图的引用(cell
,recipeImageView
,blurView
等都指向错误的东西。你需要使用数据模型找到正确的视图。
一种常见的方法是使用NSIndexPath查找单元格:
UICollectionViewCell *correctCell = [collectionView cellForItemAtIndexPath:indexPath]:
UIImageView *correctRecipeImageView = (UIImageView *)[correctCell viewWithTag:100];
/* Update your image now… */
请注意,只有当一个indexPath
始终保证指向相同的内容时,这才有效 - 如果用户可以插入/删除行,那么您也需要找出正确的indexPath,因为它也可能已经更改:
NSIndexPath *correctIndexPath = /* Use your data model to find the correct index path */
UICollectionViewCell *correctCell = [collectionView cellForItemAtIndexPath:correctIndexPath]:
UIImageView *correctRecipeImageView = (UIImageView *)[correctCell viewWithTag:100];
/* Update your image now… */
也就是说,如果AsyncImageView
是其他一些应该为你处理所有这些的类,那么你可以在主线程上调用setImageWithURL: placeholderImage:
,它应该代表你处理所有的异步加载。如果没有,我想推荐SDWebImage库,它可以:https://github.com/rs/SDWebImage
我看到你已经回答了这个问题,但仍想分享我的经验。
我有同样的问题。
在我的例子中,出现此问题的原因是以下函数:collectionView.dequeueReusableCell(...)。
每种情况下细胞的类型都相同,但数据不同:
- 在某些情况下,特定细胞的数据包含图像。
- 在某些情况下,特定细胞的数据不包含图像,它是零。
当图像为零时,我没有将图像设置为imageView。在这种情况下,集合视图重用其他单元格的图像(当前单元格的图像错误)。
解决方案非常简单:只要设置为nil,如果imageView不包含图像。
希望这会帮助你。
以上是关于UICollectionView在滚动时重新加载错误的图像的主要内容,如果未能解决你的问题,请参考以下文章
UICollectionView 单元格在可见时不断重新加载
在 UICollectionView 中重新加载数据后保持 collectionview 速度
iOS 9 UICollectionView 水平重新加载数据不起作用
UICollectionView insertItemsAtIndexPaths:似乎重新加载collectionview或自动滚动到顶部