【问题标题】:Reload constraint or update height in self-sizing tableview cell after image is downloaded下载图像后,在自定大小的 tableview 单元中重新加载约束或更新高度
【发布时间】:2017-01-25 06:43:42
【问题描述】:

我在单元格中显示 1 张图像,并且需要根据纵横比更改高度。但如果我不重新加载表格,约束不会改变,因此单元格高度也不会改变。如果我使用 'reloadData' 或重新加载特定行,没关系,但滚动性能会受到影响。其中一种方法是先下载所有图像,但我猜可能不太好。我该怎么办?

Media *media = self.post.medias[0];
NSString *imgUrlStr = media.thumbnailUrl;
[self.ivMain allowTapWithMedia:self.post.medias[0]];

UIImage* displayImage = [myCache imageFromDiskCacheForKey:imgUrlStr];

if (displayImage) {
    @try {

        [self.ivMain setImage:displayImage];
        CGFloat ivHeight = (displayImage.size.height/displayImage.size.width) * CGRectGetWidth(self.ivMain.frame);

        if (roundf(ivHeight) != roundf(self.verticalConstraintIvMain.constant))
            [self.verticalConstraintIvMain setConstant:ivHeight];

    } @catch (NSException *exception) {

    }
}
else {
    [self.ivMain setImageWithURL:[NSURL URLWithString:imgUrlStr] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {

        //image width > iv width
        //image height .. ?

        dispatch_async(dispatch_get_main_queue(), ^{
            CGFloat ivHeight = (image.size.height/image.size.width) * CGRectGetWidth(self.ivMain.frame);
            if (roundf(self.verticalConstraintIvMain.constant) != roundf(ivHeight)) {

                // [self.verticalConstraintIvMain setConstant:ivHeight];

                id view = [self superview];

                while (view && [view isKindOfClass:[UITableView class]] == NO) {
                    view = [view superview];
                }

                UITableView *tableView = (UITableView *)view;
                [tableView reloadData];
                // [tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:self.tag inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
            }
        });
    } usingActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];


}

【问题讨论】:

  • 为什么不对图片使用延迟加载?
  • 我正在使用 SDWebImage,它是异步的。
  • 但是我需要在图像下载并显示后立即更新高度。
  • 你使用了自动布局吗?
  • 是的,我正在使用自动布局和自动调整单元格。

标签: ios objective-c uitableview autolayout


【解决方案1】:

已知的解决方案是在用户滚动时不重新加载行。不可能同时进行主要的布局操作和平滑滚动。

因此,当异步图像下载调用返回时,通过查看表视图属性(继承自 UIScrollViewisDraggingisDecelerating 来检测用户是否正在滚动。如果用户正在滚动,请将“要重新加载的索引路径”放入某个存储中。最好在表视图数据源/委托上使用可变数组属性,原因如下。当用户停止滚动时,重新加载路径并清除存储。

您可以通过实现UIScrollViewDelegate 方法-scrollViewDidEndDecelerating: 来完成最后一步。表格视图的委托也是滚动视图的委托。在滚动停止时看到多个图像在实践中会产生很好的效果。

【讨论】: