在UITableView中重新加载行以更新单元格高度时出现问题

时间:2014-09-24 11:12:32

标签: objective-c uitableview afnetworking

我有自定义UITableViewCell,我使用UIImageView从网址AFNetworking设置图片。加载图像时,我想调整图像视图和单元格的大小以适合图像。

在我的tableView:cellForRowAtIndexPath:我有以下代码:

FeedItem *feedItem = self.dataArray[indexPath.row];
FeedItemCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"FeedItemCell" forIndexPath:indexPath];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:feedItem.thumbnailUrl];
[request addValue:@"image/*" forHTTPHeaderField:@"Accept"];
[cell.thumbnailImageView setImageWithURLRequest:request placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
    cell.thumbnailImageView.image = image;
    // first I set the height of the image view
    cell.thumbnailImageHeightConstraint.constant = image.size.height;
    // then I save the height in a dictionary to return it in tableView:heightForRowAtIndexPath:
    [thumbnailHeights setObject:[NSNumber numberWithFloat:thumbnailHeight] forKey:[NSNumber numberWithInteger:indexPath.row]];

    // now I reload the cell in order to have the new height applied
    [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
    NSLog(@"failed loading: %@", error);
}];

在我的tableView:heightForRowAtIndexPath:我有这个:

NSNumber *thumbnailHeightNumber = [thumbnailHeights objectForKey:[NSNumber numberWithInteger:indexPath.row]];
if (thumbnailHeightNumber != nil) { // image size has been calculated
    return thumbnailHeightNumber.floatValue;
}
return 0;

这种作品。在图像视图和单元格上正确设置高度。但是,有一些不可预测的行为:

  1. 当我滚动时,有些单元格有时会闪烁,因为如果重新加载,这很烦人。
  2. 有时错误的单元格会显示在行中。实际上,tableView:cellForRowAtIndexPath:返回的单元格内容是正确的,但它会显示之前单元格中的内容。
  3. 有时候细胞是完全空白的。再次,检查其内容似乎是正确的。
  4. 我注意到可能与此问题有关的事情。我的tableView:cellForRowAtIndexPath:方法总是被调用两次,我认为这实际上是导致我的问题。如果我删除行[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];,它只被调用一次(对于每一行)并且问题停止,但当然不会更新单元格的高度。

    另外,我不认为这个问题与细胞高度的实际变化有关。如果我为图像和单元格高度设置固定高度,则在调用reloadRowsAtIndexPaths:withRowAnimation:时仍然会产生相同的副作用。

    所以我希望能解决这个问题,或者其他一些方法来实现我的动态细胞高度目标。

1 个答案:

答案 0 :(得分:1)

setImageWithURLRequest:request:placeholderImage:success:failure:的调用是异步的,因此cell.thumbnailImageView将无法填充或(如果正在重新使用该单元格)中包含先前的图像数据,直到setImageWithURLRequest成功,可能在tableView:cellForRowAtIndexPath:已经返回单元格后的某个时间。如果setImageWithURLRequest失败,则您的单元格将保留未更改/未配置的缩略图图像视图。

您可以在placeholder:参数中提供一个图像,该图像将一直显示,直到调用success块,然后至少您还有一个故障情况的后备。

随着各个单元的成功块在一段时间后异步调用,表可能会闪烁,每个单元都会强制重新加载不同的行。

除非您事先知道缩略图图像都是固定大小(然后可以轻松使用标准占位符图像),否则我建议您在表格视图的numberOfRowsInSection:更改之前预先加载相关的缩略图图像返回值,从而触发对tableView:cellForRowAtIndexPath:的调用。这样,您就可以在单元格中返回完全配置的图像。