Я бился головой об стену на этом и искал повсюду в поисках решения, но безрезультатно:
У меня есть большой массив данных, извлеченных из Интернета, и я использую ABTableViewCell, чтобы он работал плавно, отрисовывая все внутри contentView каждой ячейки, чтобы избежать замедления прокрутки UILabels и UIImageViews.
Это отлично подходит для отображения текста, но я сталкиваюсь с проблемой с изображениями из-за того, что их загрузка занимает много времени. Кажется, я не могу найти способ заставить contentView каждой отображаемой ячейки перерисовывать себя после загрузки соответствующего изображения. Я должен указать, что я рисую не метки и imageView, а только contentView, чтобы сэкономить память.
Сейчас таблица ведет себя так:
- Загрузить: текст отображается, изображений нет
- Прокрутка вверх или вниз: изображения, наконец, появляются, когда ячейки уходят с экрана.
Образец проекта находится здесь.
Код:
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), но я не могу заставить его работать так, как должно. Мысли? Большое спасибо!
Окончательная правка: решение
Итак, как и предполагалось, проблема заключалась в том, что видимым ячейкам не предлагалось перерисовать и обновить загруженное изображение после завершения вызова.
Я воспользовался справкой, предоставленной в ответах ниже, чтобы составить решение, которое хорошо подходит для моих нужд:
Добавлен обратный вызов в последний метод, который вызывает асинхронный загрузчик изображений:
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!