我正在使用SDWebImage为我的表格单元格加载图片,使用以下代码:
[cell.coverImage sd_setImageWithURL:[self.dataInJSONModel.Content[indexPath.row] CoverImage] placeholderImage:[UIImage imageNamed:@"imageplaceholder_general"]];
问题是当我向上和向下滚动时,图像被插入到错误的单元格中。在阅读StackOverflow上有关此问题的一些帖子后,我怀疑这是因为我们滚动时会重复使用单元格,因此可以将图像的异步下载放置在已更改的单元格索引路径上。
因此我实施了一些改变,例如:
SDWebImageManager *manager = [SDWebImageManager sharedManager];
UIImageView * cellCoverImage = cell.coverImage;
[manager downloadImageWithURL:[self.dataInJSONModel.Content[indexPath.row] CoverImage] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL * oriURL) {
NSArray *visibleIndexPaths = [tableView indexPathsForVisibleRows];
if ([visibleIndexPaths containsObject:indexPath]) {
cellCoverImage.image = image;
}
}];
甚至比较网址:
SDWebImageManager *manager = [SDWebImageManager sharedManager];
UIImageView * cellCoverImage = cell.coverImage;
[manager downloadImageWithURL:[self.dataInJSONModel.Content[indexPath.row] CoverImage] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL * oriURL) {
if([oriURL isEqual:[self.dataInJSONModel.Content[indexPath.row] CoverImage]])
{
cell.coverImage.image = image;
}
}];
问题仍然存在。或者我可能错误地编程了它?在网上找到了一些建议,但还没有找到具体的解决方案。
需要帮助!
修改
我已经对它进行了一些更改但仍然不起作用:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NewsFeedCell * cell = [tableView dequeueReusableCellWithIdentifier:@"NewsFeedCell" forIndexPath:indexPath];
if (self.dataInJSONModel)
{
cell.coverImage.image = nil;
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadImageWithURL:[self.dataInJSONModel.Content[indexPath.row] CoverImage] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL * oriURL) {
if ([cell isEqual:[self.tableView cellForRowAtIndexPath:indexPath]])
{
cell.coverImage.image = image;
}
}];
}
答案 0 :(得分:3)
我遇到了同样的问题,并尝试分配.image = nil,但不能正常工作。
最后,我的意思是使用取消操作覆盖UITableViewCell中的prepareForReuse:
- (void)prepareForReuse
{
[super prepareForReuse];
[_imageView sd_cancelCurrentImageLoad];
}
答案 1 :(得分:2)
在SDWebImage Github页面上发布了问题并得到了解决我问题的人的建议!我只是在我的单元格的实现文件中覆盖prepareForReuse方法,并使受影响的imageView的图像无效。
未来读者的示例代码:
In my NewsFeedCell.m
- (void) prepareForReuse
{
[super prepareForReuse];
self.coverImage.image = NULL;
}
这解决了这个问题!我在GitHub上打开的问题是https://github.com/rs/SDWebImage/issues/1024,如果你们有人想看到的话。
答案 2 :(得分:1)
我尝试了大部分这些解决方案,花了一些时间来解决这个问题。我有2个解决方案适合我。
在 cellForRow 中添加以下内容:
cell.imageView.sd_cancelCurrentImageLoad()
然后在单元格中:
func prepareForReuse() {
imageView.image = UIImage.placeholderImage() // or nill
}
这不是真正的解决方案,因为您实际停止了图像下载并浪费了已下载的数据。
选择适合您的动画,然后尝试:
func setImageAnimated(imageUrl:URL, placeholderImage:UIImage) {
self.sd_setImage(with: imageUrl, placeholderImage: placeholderImage , options:SDWebImageOptions.avoidAutoSetImage, completed: { (image, error, cacheType, url) in
if cacheType == SDImageCacheType.none {
UIView.transition(with: self.superview!, duration: 0.2, options: [.transitionCrossDissolve ,.allowUserInteraction, .curveEaseIn], animations: {
self.image = image
}, completion: { (completed) in
})
} else {
self.image = image
}
})
}
答案 3 :(得分:0)
你对问题的分析是正确的,只是没有正确地执行它。
cellForRowAtIndexPath
的一些伪代码......
- set the cell.imageView.image to nil to wipe out
previous use of cell image view contents
- get the URL from data source
- initiate asynchronous download with completion ^{
//check the cell is still the correct cell
if ([cell isEqual: [collectionView cellForRowAtIndexPath:indexPath]]) {
cell.imageView.image = image
}
}
你做错了几件事 - 在您知道需要之前(在完成块中),不要获取对单元格图像视图的引用 - 不检查visibleIndexPaths,indexPath可能仍然可见但分配给不同的单元格(例如,如果已滚动然后再打开)。我在这里使用的'cell isEqual'技术应该足以满足所有情况。
您还可以通过覆盖单元格-prepareForReuse
方法来为循环单元格找出旧单元格内容。
答案 4 :(得分:0)
这里的明显错误是你没有考虑使用Blocks。本质上,完成发生在后台线程上,所有UI更新必须发生在主线程上。
简单的解决方案是;
dispatch_async(dispatch_get_main_queue(), ^{
cell.coverImage.image = image;
});
此外,如果您打算在完成块中引用tableView,则应使用弱引用。