私はこれで頭を壁にぶつけて、役に立たない解決策を遠くまで探しました:
Web から取得した大量のデータがあり、Loren Brichter の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;
他に 1 つまたは 2 つの微調整があった可能性がありますが、これらがここでの主な問題でした。SOコミュニティに再び感謝します!