0

私は、コレクションビューに表示されるたくさんの大きな画像ファイルを持つアプリケーションを構築しています。イメージのサイズのため、URLからサムネイルを作成するだけでなく、イメージキャッシュを使用する方がはるかに迅速です。私が最初にGCDを使ってcellForItemAtIndexPathでこれを実装したとき、私はUIのラグを大幅に減らしましたが、コレクションビューを表示してスクロールすると、セルの画像がちらつき、急激に変化することに気付きました。私は同様の問題に関する他の記事を見つけました。彼らは最初にセルが無かったかどうかを調べることで問題を解決するべきだと言いましたが、残念ながらこれは画像の多くがロードされないという別の問題を引き起こしています。誰もがこれを修正する方法を知っていますか?iOS - cellForItemAtIndexPath画像読み込みの問題を修正しました

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 
PhotoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath]; 
ObjectWithPhoto *object = self.objects[indexPath.item]; 
cell.imageView.image = nil; 

NSString *imageName = object.imageName; 
NSString *imageKey = [NSString stringWithFormat:@"%@_thumbnail", imageName]; 
if ([[ImageCache sharedCache] imageForKey:imageKey]) { 
    cell.imageView.image = [[ImageCache sharedCache] imageForKey:imageKey]; 
} else { 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { 
     NSURL *imageURL = [[NSBundle mainBundle] URLForResource:imageName withExtension:@"jpg"]; 
     CGSize imageSize = CGSizeMake(self.view.frame.size.width, self.view.frame.size.width); 
     UIImage *thumbnail = [UIImage createThumbnailFromURL:imageURL imageSize:imageSize]; 
     [[ImageCache sharedCache] setImage:thumbnail forKey:imageKey]; 
     dispatch_async(dispatch_get_main_queue(), ^(void) { 
      PhotoCell *cellToUpdate = (id)[collectionView cellForItemAtIndexPath:indexPath]; 
      if (cellToUpdate) { 
       cellToUpdate.imageView.image = thumbnail; 
      } else { 
       NSLog(@"cell is no long visible"); 
      } 
     }); 
    }); 
} 
return cell; 
} 

答えて

1

たぶん、あなたはあなたのソリューションに満足しているが、私はありませんよ。あなたが必要とするイメージがキャッシュされていない場合に、イメージをクリアしない(またはプレースホルダに設定しない)ことが、あなたが見ている少なくとも1つの奇妙な情報源だと私は思います。スクロールを開始するとすぐに、イメージはキャッシュには格納されませんが、再利用されたセルのイメージは、他のindexPathのイメージに設定されることになります。私は、誰かが自分のcellForItemのデータソースメソッドを呼び出すと、セルに値を突く見るたびにそう、1 ...

if ([[ImageCache sharedCache] imageForKey:imageKey]) { 
    cell.imageView.image = [[ImageCache sharedCache] imageForKey:imageKey]; 
} else { 
    // fix one: clear the cell's image now, if it's set, it's wrong... 
    cell.imageView.image = nil; // or a placeholder 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { 
     // ... 

セカンドを修正、私は黄色の旗を投げます。これはより簡潔でより丁寧です。

cell.imageView.image = nil; // or a placeholder 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { 
    NSURL *imageURL = [[NSBundle mainBundle] URLForResource:imageName withExtension:@"jpg"]; 
    CGSize imageSize = CGSizeMake(self.view.frame.size.width, self.view.frame.size.width); 
    UIImage *thumbnail = [UIImage createThumbnailFromURL:imageURL imageSize:imageSize]; 
    [[ImageCache sharedCache] setImage:thumbnail forKey:imageKey]; 
    dispatch_async(dispatch_get_main_queue(), ^(void) { 
     // fix two: don't get the cell. we know the index path, reload it! 
     [collectionView reloadItemsAtIndexPaths:@[indexPath]]; 
     // deleted evil stuff that was here 
    }); 
}); 
+0

私の元のコードを見ると、最初に画像をゼロに設定していることがわかります。あなたのソリューションの残りの部分は素晴らしいですが、ありがとう! – Grambo

0

私はこれについての修正を考え出しました。セルがまだ利用可能かどうかをチェックするとき、私はまだスクリーン上でそれを見ることができると誓ったとしても、それは無限に戻るように見えました。このことを念頭に置いて、コレクションのビューに、セルが戻ってこない場合はデータをリロードするように指示しました。スムーズなスクロールと、ちらつきのない画像がいっぱい。

PhotoCell *cellToUpdate = (id)[self.collectionView cellForItemAtIndexPath:indexPath]; 
if (cellToUpdate) { 
    cellToUpdate.imageView.image = thumbnail; 
} else { 
    NSLog(@"cell is no long visible"); 
    [self.collectionView reloadData]; 
} 
関連する問題