下载图像时 UITableViewCell 高度调整大小
Posted
技术标签:
【中文标题】下载图像时 UITableViewCell 高度调整大小【英文标题】:UITableViewCell height resize when image is downloaded 【发布时间】:2012-10-17 18:52:18 【问题描述】:我正在使用UIImageView+AFNetworking
类别进行异步图像加载。一切正常,但我尝试了几件事,但在根据下载的图像调整单元格的高度时没有成功。我希望图像适合单元格的宽度,但要调整高度,但我不知道如何实现。我尝试重新加载下载图像的行,但这只会导致cellForRowAtIndexPath
再次触发并再次设置所有内容,等等。几乎是递归。
我正在计算新的图像大小差异并将其存储在 NSMutableArray
中,然后在 UIImageView 的 setImageWithURLRequest:placeholderImage:success:
的成功块中重新加载该行。
我在heightForRowAtIndexPath
中得到了几行的正确高度,但随后表格开始变得怪异,一切都在叠加,等等。
有什么想法吗?
谢谢!
编辑
我最终使用了 Ezeki 的答案。我还写了一篇关于该主题的帖子,并制作了一个使用这种技术的示例应用程序。
查看here。
【问题讨论】:
【参考方案1】:对我来说这是可行的:
您检查缓存图像是否可用,如果可用,则将其设置为图像,如果不可用,则将其下载,然后通过调用重新加载索引路径重置表的布局。
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *broadcastTableCellIdentifier = @"BlockbusterTableViewCell";
BlockbusterTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:broadcastTableCellIdentifier];
if (cell == nil)
cell = [[BlockbusterTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:broadcastTableCellIdentifier];
[self configureCell:cell atIndexPath:indexPath];
return cell;
-(void)configureCell:(BlockbusterTableViewCell*)cell atIndexPath:(NSIndexPath*)indexPath
SportData *data = [self.webShared.arrSportsData objectAtIndex:self.selectedEvent];
BroadcastData *broadcastData = [data.broadcastData objectAtIndex:indexPath.row];
NSURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:broadcastData.image]];
AFImageDownloader *downloader = [UIImageView sharedImageDownloader];
id <AFImageRequestCache> imageCache = downloader.imageCache;
UIImage *cacheimage = [imageCache imageforRequest:urlRequest withAdditionalIdentifier:nil];
if (cell.imgBroadcast.image != cacheimage)
[cell.imgBroadcast setImageWithURLRequest:urlRequest placeholderImage:[UIImage imageNamed:@"placeholder_smaller"] success:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, UIImage * _Nonnull image)
cell.imgBroadcast.image = image;
[self.tableViewBroadcast beginUpdates];
[self.tableViewBroadcast reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableViewBroadcast endUpdates];
failure:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSError * _Nonnull error)
];
else
cell.imgBroadcast.image =cacheimage;
cell.lblTitle.text = broadcastData.title;
cell.lblText.text = broadcastData.text;
cell.lblEventDateTime.text = [self eventTime:broadcastData.eventTime];
【讨论】:
【参考方案2】:您需要将下载的图像存储在内存或磁盘上,因此下次尝试从该 URL 获取图像时,您将从缓存中收到。
因此,如果您这样做,则必须执行以下操作:
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
并且您应该在表格视图数据源的这种方法中返回新单元格的高度:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
我建议您使用SDWebImage library 而不是AFNetworking
,因为它可以为您将图像缓存到内存缓存和磁盘,并且非常易于使用。因此,如果您决定使用它,您的下载图像代码将如下所示:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
...
[cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:@"placeholder.png"]
success:^(UIImage *image, BOOL cached)
// save height of an image to some cache
[self.heightsCache setObject:[NSNumber numberWithFloat:imHeight]
forKey:urlKey];
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:@[indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
failure:^(NSError *error) ... failure code here ...];
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
// try to get image height from your own heights cache
// if its is not there return default one
CGFloat height = [[self.heightsCache objectForKey:urlKeyFromModelsArrayForThisCell] floatValue];
...
return newHeight;
【讨论】:
谢谢,这是一个很好的建议!顺便说一句,AFNetworking
也处理缓存。无论如何,我让它工作了,但是由于重新加载,tableview 滚动现在非常生涩。也许我会尝试使用SDWebImagePrecacher
预加载图像。我必须找到一种计算单元格高度的方法,因为单元格中还有其他子视图。
@Jure 您找到问题的完整解决方案了吗?我正在经历同样的问题。你能帮忙吗?
self.heightsCache 属性在哪里声明?
这只是一个 NSMutableDictionary 属性,您可以在 ViewController.h 文件或 ViewController.m 中使用类别扩展声明。不要忘记在 init 或 viewDidLoad 中对其进行初始化。这个可变字典将 url 字符串作为键,将 NSNumber 作为值。
@Ezeki 我尝试以这种方式实现我的 tableview,但我发现有几个缺点: 1. 内存 - 大列表需要大量内存,同时调用 [tableView beginUpdates]; [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; [tableView endUpdates];
(我看到我的列表将近 30mb)2. 它不是那么顺利以上是关于下载图像时 UITableViewCell 高度调整大小的主要内容,如果未能解决你的问题,请参考以下文章
计算取决于单元格宽度和异步加载的图像的 UITableViewCell 的高度
iOS7根据从API下载的图像高度动态调整TableViewCell的高度