UITableView - 滚动时更改单元格图像

时间:2015-09-05 15:10:42

标签: ios objective-c uitableview

我的问题是,当我滚动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;
 }

请帮帮我

6 个答案:

答案 0 :(得分:20)

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

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

should.not.exist(never_declared);
expect(never_declared).to.not.exist;
expect(never_declared).to.not.exist;
expect(never_declared).to.be.undefined;
expect(never_declared).to.be.an('undefined');
assert.isNotObject(never_declared);
assert.isUndefined(never_declared);

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

cell.tag = indexPath.row

答案 1 :(得分:6)

你正在重复使用旧细胞,这是一件好事。但是,您没有在单元格的图像视图中初始化图像,这不是一件好事。您正在描述的内容是因为旧单元格(已为该单元格加载了图像)用于新单元格。然后,您将在背景中加载该单元格的图像(这也是好的)但是该图像需要一些时间才能完全加载。与此同时,显示已加载在旧单元格上的图像(这就是您在该单元格中看到错误图像的原因,片刻之后)。

解决方案?添加

thumbnailImageView.image = nil

thumbnailImageView.image = someDefaultImageWhileYourRealOneLoads

dispatch_queue_t concurrentQueue ...之前。

这样,当真实的图像加载时,你不会看到旧的(不相关的)图像。

我希望这会有所帮助。祝你好运。

答案 2 :(得分:3)

因为你的ImageView被加载到一个async调度调用中,该调用不在主线程上并且正在某个其他线程中被调用,因此从URL获取数据然后转换它会有延迟到了UIImage。如您所知,这个过程需要一些时间,但您正在以更快的速度滚动tableview。正如您所知cellForRowAtIndexPath重用了窗口外的任何单元格,因此正在重用的单元格可能无法获取之前在窗口中时要检索的图像数据。因此,它会加载错误的数据,然后当针对该特定单元格触发async时,单元格会加载该图像,但会出现延迟。

为了克服这个功能,Chronch指出你可以将imageview保留为n或者你可以使用AFNetworking自己的UIImageView catagory,它有一个极好的类来非常优雅地加载imageview图像

我会给你一个链接AFNetworking

答案 3 :(得分:1)

我只会在https://plus.google.com/share?url=www.andrewburns.info%2Fblog%2Ffirstsortedvalue+function+in+Qlikview+script.php处进行所有数据绑定,因为在cellForRowAtIndexPath中,您的单元格尚未被绘制。 您可以使用的另一种解决方案是AFNetworking,就像我之前提到的其他人一样。

答案 4 :(得分:1)

Swift 3.0

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

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

答案 5 :(得分:0)

不要担心添加两行并感觉自由

 cell.thumbnailimages.image=nil

  cell.thumbnailimages.setImageWith(imageurl!)

我认为这两行可以解决您的问题在此先感谢