UITableView - 滚动时单元格图片改变

9

你好,我的问题是当我滚动TableView时,图像会出现在错误的单元格中,几秒钟后正确的图像才会出现。

以下是我的代码:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

// Configure the cell...
if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] ;
}

[cell setOpaque:NO];
[cell setBackgroundColor: [UIColor clearColor]];

PlaceData *data = [tableData objectAtIndex:indexPath.row];
UILabel *nameLabel = (UILabel *)[cell viewWithTag:100];
UILabel *sciNameLabel = (UILabel *)[cell viewWithTag:200];
UIImageView *thumbnailImageView = (UIImageView *)[cell viewWithTag:300];
nameLabel.text = data.name;
sciNameLabel.text = data.scientific_name;


// get a dispatch queue
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// this will start the image loading in bg
dispatch_async(concurrentQueue, ^{
    NSURL *urlToPicture = [NSURL URLWithString:[NSString stringWithFormat:@"%@", data.thumbnail]];
    NSData *imgData = [NSData dataWithContentsOfURL:urlToPicture options:0 error:nil];

    // This will set the image when loading is finished
    dispatch_async(dispatch_get_main_queue(), ^{
        UIImage *tmpImage = [[UIImage alloc] initWithData:imgData];
        thumbnailImageView.image = tmpImage;
        //dispatch_release(concurrentQueue);
         });
     });

       return cell;
 }

请帮助我。


https://stackoverflow.com/questions/43866409/collectionview-in-tableviewcell-scroll-isnt-smooth-in-swift3/43907018#43907018 - Sanju
6个回答

22

您可以尝试将以下代码添加到您的cellForRowAtIndexPath中 -

1)为自定义单元格分配索引值。例如,

cell.tag = indexPath.row

2)在主线程上,在分配图像之前,通过将其与标记匹配来检查图像是否属于相应的单元格。

dispatch_async(dispatch_get_main_queue(), ^{
    if(cell.tag == indexPath.row) {
      UIImage *tmpImage = [[UIImage alloc] initWithData:imgData];
      thumbnailImageView.image = tmpImage;
    }});
 });

6
您正在重复使用旧单元格,这是一件好事。但是,您没有初始化单元格图像视图中的图像,这不是一件好事。您所描述的情况是因为一个旧的单元格,其中加载了该单元格的图像,被用于新单元格。然后,在后台加载该单元格的图像(这也是好的),但需要一些时间才能完全加载该图像。在此期间,已经加载到旧单元格上的图像会显示出来(这就是您在该单元格中看到错误图像的原因,持续了一段时间)。
解决方案是添加以下内容之一:
thumbnailImageView.image = nil

或者

thumbnailImageView.image = someDefaultImageWhileYourRealOneLoads

dispatch_queue_t并行队列之前,这样一来,在实际的图片加载过程中,您就不会看到旧的(无关的)图片。希望这有所帮助。祝你好运。

感谢您的回答,但它仍然显示旧图像。 - Tae Chatnaratanakun
1
谢谢,我已经寻找解决方案几个小时了,你的是最简单和最好的! - DazChong
在设置单元格图像之前将图像设置为nil,这对我解决了问题。谢谢。 - Jeff

3
由于您的ImageView是在非主线程中加载的异步调用,因此存在从URL获取数据并将其转换为UIImage的延迟。如您所知,这个过程需要一些时间,但您正在以更快的速度滚动表格视图。而且,如您所知,“cellForRowAtIndexPath”会重用任何窗口外的单元格,因此正在被重用的单元格可能没有检索先前在窗口中应获取的图像数据。因此,它会加载错误的数据,然后再次启动该特定单元格的“async”时,该单元格会加载该图像,但会出现延迟。
为了克服这个问题,Chronch指出您可以将imageview保留为空,或者您可以使用AFNetworking的UIImageView类别,该类别具有优秀的类来相当优雅地加载imageview图像。
我会给您留下一个链接:AFNetworking

1

Swift 3.0

DispatchQueue.main.async(execute: {() -> Void in

    if cell.tag == indexPath.row {
        var tmpImage = UIImage(data: imgData)
        thumbnailImageView.image = tmpImage
    }
})

1
我会在- tableView:willDisplayCell:forRowAtIndexPath:中进行所有数据绑定,因为在cellForRowAtIndexPath中,您的单元格尚未绘制。另一个解决方案是使用AFNetworking,就像其他人在我之前提到的那样。

0
cell.thumbnailimages.image=nil

cell.thumbnailimages.setImageWith(imageurl!)

我认为这两行代码可以解决你的问题。


如果有图像链接,就将图像设置到单元格的缩略图上。 - Jeff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接