UICollectionView
用于显示图像。它工作正常。
问题是当我滚动UICollectionView
时,一些可见的单元格现在是不可见的,当我向后滚动以便它们再次可见时,我看到它们没有正确显示。
所以会发生imageA
位于索引0而imageB
位于索引1.现在滚动并返回原始滚动位置时再次加载这些单元格时,它们的位置要么切换,要么两个细胞都有相同的图像。
最初:
重新加载单元格后
代码:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MyCell"
forIndexPath:indexPath];
DLog(@"url at index %d : %@", indexPath.row, ((MyObject *)[self.list.array objectAtIndex:indexPath.row]).imageUrl);
MyObject *object = (MyObject *)[self.list.array objectAtIndex:indexPath.row];
// Get image in separate thread
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Get image to display
UIImage * tempImage = object.image;
if (tempImage)
{
// Run code to set image to UIImageView in main thread only.
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageView.image = tempImage;
});
}
else
{
// Download failed.
DLog(@"Downloaded image is nil.");
}
});
return cell;
}
我记录了图片网址的值,并记录了正确的值。
答案 0 :(得分:5)
我也使用了这个技巧,但是线程和线程之间的索引弄得一团糟,所以我搜索了一下,我在GitHub上找到了一个很棒的库。
您只需要#import <SDWebImage/UIImageView+WebCache.h>
到项目中,并且只需使用以下代码即可在下载图像时定义占位符:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MyCell"
forIndexPath:indexPath];
DLog(@"url at index %d : %@", indexPath.row, ((MyObject *)[self.list.array objectAtIndex:indexPath.row]).imageUrl);
MyObject *object = (MyObject *)[self.list.array objectAtIndex:indexPath.row];
[cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:@"placeholder.png"]];
return cell;
}
它还可以缓存下载的图像并为您提供出色的性能。
希望它会对你有所帮助!
答案 1 :(得分:1)
为什么你想知道一段时间后他们会转到他们的位置?你打电话
cell.imageView.image = tempImage;
异步。这意味着执行不会在图像更改时等待,并使用旧图像显示出列单元格。
答案 2 :(得分:1)
这里有几个问题,但主要是你看到的问题是因为单元格引用不再指向同一个Cell。作为一项学习练习,保留您的代码(或至少是代码的总体布局),您可以通过indexPath获取对您希望项目应用的单元格的引用来解决问题,如果它是仍在显示,分配图像。
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MyCell"
forIndexPath:indexPath];
DLog(@"url at index %d : %@", indexPath.item, ((MyObject *)[self.list.array objectAtIndex:indexPath.item]).imageUrl);
MyObject *object = (MyObject *)[self.list.array objectAtIndex:indexPath.item];
// get a weak reference to collectionViewController (assume your code is in a UICollectionViewCcontroller)
__weak MyCollectionViewController *weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Get image to display
UIImage * tempImage = object.image;
// check if the cell is still visible
if ([weakSelf.collectionView.indexPathsForVisibleItems containsObject:indexPath]) {
if (tempImage)
{
// Run code to set image to UIImageView in main thread only.
dispatch_async(dispatch_get_main_queue(), ^{
// we get a reference to the cell via it's indexPath
MyCell *cell = (MyCell *)[weakSelf.collectionView cellForItemAtIndexPath:indexPath];
cell.imageView.image = tempImage;
});
}
else
{
// Download failed.
DLog(@"Downloaded image is nil.");
}
}
});
return cell;
}
正如Erid建议的那样,使用像SDWebImage这样的东西并将图像url存储在MyObject类中并使用SDWebimage的setImageWithURL设置cell.imageView.image肯定会更好(我个人会写出图像对象类中的检索和图像引用。)
哦,还有一点,您应该将indexPath.section和indexPath.item用于UICollectionViews,将indexPath.row用于UITableView.s