【发布时间】:2012-08-16 03:01:49
【问题描述】:
我一直在这个问题上撞墙并四处寻找无济于事的解决方案:
我从网络上提取了大量数据,我正在使用 Loren Brichter 的 ABTableViewCell 通过在每个单元格的 contentView 内绘制所有内容来使其平稳运行,以避免 UILabel 和 UIImageViews 减慢滚动速度。
这非常适合显示文本,但我遇到了图像问题,因为下载它们需要时间。一旦下载了相应的图像,我似乎无法找到一种方法来强制显示的每个单元格的 contentView 重新绘制自身。我必须指出我不是在绘制标签和图像视图,而只是为了节省内存而绘制 contentView。
现在表格的行为如下:
- 加载:显示文本,无图像
- 向上或向下滚动:最终图像 一旦单元格移出屏幕就会显示
一个示例项目是here
代码:
ABTableViewCell.h
@interface ABTableViewCell : UITableViewCell
{
UIView *contentView;
}
ABTableViewCell.m
- (void)setNeedsDisplay
{
[contentView setNeedsDisplay];
[super setNeedsDisplay];
}
- (void)drawContentView:(CGRect)r
{
// subclasses implement this
}
TableCellLayout.h
#import "ABTableViewCell.h"
@interface TableCellLayout : ABTableViewCell {
}
@property (nonatomic, copy) UIImage *cellImage;
@property (nonatomic, copy) NSString *cellName;
TableCellLayout.m
#import "TableCellLayout.h"
@implementation TableCellLayout
@synthesize cellImage, cellName;
- (void)setCellName:(NSString *)s
{
cellName = [s copy];
[self setNeedsDisplay];
}
- (void)setCellImage:(UIImage *)s
{
cellImage = [s copy];
[self setNeedsDisplay];
}
- (void)drawContentView:(CGRect)r
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextFillRect(context, r);
[cellImage drawAtPoint:p];
[cellName drawAtPoint:p withFont:cellFont];
}
TableViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
TableCellLayout *cell = (TableCellLayout *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[TableCellLayout alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.cellName = [[array valueForKey:@"name"] objectAtIndex:indexPath.row];
cell.cellImage = [UIImage imageNamed:@"placeholder.png"]; // add a placeholder
NSString *imageURL = [[array valueForKey:@"imageLink"] objectAtIndex:indexPath.row];
NSURL *theURL = [NSURL URLWithString:imageURL];
if (asynchronousImageLoader == nil){
asynchronousImageLoader = [[AsynchronousImages alloc] init];
}
[asynchronousImageLoader loadImageFromURL:theURL];
cell.cellImage = asynchronousImageLoader.image;
return cell;
}
这是图像准备好后 AsynchronousImageLoader 调用的最后一个方法:
- (void)setupImage:(UIImage*)thumbnail {
self.image = thumbnail;
[self setNeedsLayout];
}
我只需要正确的方法来告诉我的可见单元格在下载行的图像后重新绘制自己。我想我应该在最终方法(setupImage)中添加一些东西——但我似乎无法让它按应有的方式工作。想法?非常感谢!
最终编辑:解决方案
没错,正如所怀疑的那样,问题在于调用完成后,没有告知可见单元格重绘并更新为下载的图像。
我使用以下答案提供的帮助来制定一个适合我需求的解决方案:
在异步图片下载器调用的final方法中添加回调:
AsyncImageView.m
- (void)setupImage:(UIImage*)thumbnail {
self.cellImage = thumbnail;
[cell setNeedsDisplay];
}
注意:我还在图像下载器类的初始化中设置了一个本地占位符图像,只是为了美化一点。
然后在我的 cellForRowAtIndexPath 中:
NSURL *theURL = [NSURL URLWithString:imageURL];
AsyncImageView *aSync = [[AsyncImageView alloc] initWithFrame:CGRectMake(0, 0, 20, cell.bounds.size.height)];
[aSync loadImageFromURL:theURL];
cell.cellImageView = aSync;
return cell;
可能还有一两个其他调整,但这些是这里的主要问题。再次感谢 SO 社区!
【问题讨论】:
-
你解决了吗?我在两天前用我测试过的代码更新了我的答案。请您检查详细信息并确认已解决。谢谢!
-
嗨,是的,社区再次变得很棒。我会接受答案并写一个简短的编辑来展示我做了什么来让这一切正常工作。感谢您的帮助!
-
很高兴听到,乐于助人!
标签: iphone objective-c asynchronous uitableview custom-cell