5

リモートサイトからUITableViewにサムネイル画像を読み込もうとしています。これを非同期で実行したいのですが、サムネイル画像用に貧乏人のキャッシュを実装したいと思います。これが私のコードスニペットです(問題のある動作については以下で説明します):

@property (nonatomic, strong) NSMutableDictionary *thumbnailsCache;

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

// ...after obtaining the cell:

NSString *thumbnailCacheKey = [NSString stringWithFormat:@"cache%d", indexPath.row];

if (![[self.thumbnailsCache allKeys] containsObject:thumbnailCacheKey]) {
    
    // thumbnail for this row is not found in cache, so get it from remote website
    __block NSData *image = nil;        
    dispatch_queue_t imageQueue = dispatch_queue_create("queueForCellImage", NULL);
    dispatch_async(imageQueue, ^{
        NSString *thumbnailURL = myCustomFunctionGetThumbnailURL:indexPath.row;
        image = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:thumbnailURL]];
        dispatch_async(dispatch_get_main_queue(), ^{
            cell.imageView.image = [UIImage imageWithData:image];
        });
    });
    dispatch_release(imageQueue);
    [self.thumbnailsCache setObject:image forKey:thumbnailCacheKey];
    
} else {
    
    // thumbnail is in cache
    NSData *image = [self.thumbnailsCache objectForKey:thumbnailCacheKey];
    dispatch_async(dispatch_get_main_queue(), ^{
        cell.imageView.image = [UIImage imageWithData:image];
    });
    
}

したがって、問題のある動作は次のとおりです。

  1. UITableViewが読み込まれると、サムネイルはセルの初期セットに表示されません。セルが画面から移動してから上に移動した場合にのみ、サムネイルが表示されます。

  2. キャッシュがまったく機能していません。私の知る限り、サムネイルをキャッシュに保存することはできません。つまり、この行は失敗します。

    [self.thumbnailsCache setObject:image forKey:thumbnailCacheKey];

  3. GCDキューは、セルごとに作成/解放されます。さらに、キュー名は毎回同じです。これは悪い習慣ですか?

間違っていると思われることや、一般的なアプローチのコメントを指摘していただければ幸いです。ありがとう。

アップデート:

  1. 解決済み:reloadRowsAtIndexPathsの呼び出しを追加したところ、サムネイル画像が表示される最初の行に読み込まれるようになりました

  2. 解決済み:失敗した理由は、他のスレッドがそのオブジェクトの設定を完了する前に、画像オブジェクトをディクショナリに追加していたためです。プロパティディクショナリにオブジェクトを追加するインスタンスメソッドを作成しました。これにより、ブロック内からオブジェクトを呼び出すことができ、画像オブジェクトの設定後にオブジェクトが追加されるようになります。

4

2 に答える 2

3

SDWebImageを必ず確認してください。それはまさにあなたが探しているものです。SDWebImage も非常に高速で、マルチコア CPU を使用できます。

于 2012-04-14T18:10:32.150 に答える
1

1) 最初の画像が表示されない理由は、セルが image = nil でレンダリングされ、画像ビューをインテリジェントに非表示にするためです。

2) この行をブロック内に移動しようとしましたか?

[self.thumbnailsCache setObject:image forKey:thumbnailCacheKey];

3) これは、デバッグするキューを区別し、コンソールから情報を取得するための単なる方法です。アプリがクラッシュした場合、キューの名前を確認できます。同じ操作を行うため、これに同じ名前を付けても問題ありません。同じロジックを使用している場合、別のテーブル ビューでこの名前を使用したくないでしょう。

于 2012-04-14T17:58:31.320 に答える