我目前正在使用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;
}
}];
}
我遇到了同样的问题,并尝试分配.image = nil,但没有工作。
最后,我的意思是使用取消操作覆盖UITableViewCell中的prepareForReuse:
- (void)prepareForReuse
{
[super prepareForReuse];
[_imageView sd_cancelCurrentImageLoad];
}
在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个解决方案适合我。
在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
}
})
}
你对问题的分析是正确的,只是没有正确地执行它。
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
方法来为循环细胞排除旧细胞内容。
这里的明显错误是你没有考虑使用Blocks。本质上,完成发生在后台线程上,所有UI更新必须在主线程上进行。
简单的解决方案是;
dispatch_async(dispatch_get_main_queue(), ^{
cell.coverImage.image = image;
});
此外,如果您打算在完成块中引用tableView,则应使用弱引用。