通常のUITableView + asyncのダウンロード+キャッシュ手法の独自の風味を引き出そうとしています。私がやっていることはcellForRowAtIndexPathでデキューます各セルのために、次のとおりです。UITableViewCell画像を取得して、UITableViewをスクロールせずにダウンロードした画像に更新する方法
1-Check if it's corresponding thumbnail image is already 'cached' in /Library/Caches
2-If it is, just use that.
3-If not, load a default image and enqueue an NSInvocationOperation to take care of it:
4a-The NSInvocationOperation gets the image from a remote server
4b-Does the UIGraphicsBeginContext thing to scale down the image to 40x40
4c-saves the scaled down version to /Library/Cache
4d-'SHOULD' update the cell's image to the new downloaded and downsized image, if the cell is still visible.
しかし、私は手動でバックスクリーンにそれらをオフにスクロールしない限り、細胞がそれらのイメージを更新するために取得する方法を見つけ出すことはできません。私が引き出すことができた唯一のハックは、performSelectorOnMainThreadによってNSOperationがメインスレッドを呼び出すことです。メインスレッドは[viewtable reloadData]を呼び出すことができます。しかし、これは無駄に思えます。セルの新しいイメージが準備されるたびに、テーブル全体をリロードしています。
私は主スレッドにブールフラグを設定してから、scrollViewDidEndDeceleratingを実行すると、フラグが設定されていれば[viewtable reloadData]が呼び出されます。このアプローチでは、ユーザーがスクロールを完了したときにセルがリフレッシュされます。
しかし、キャッシュされた画像がまだ表示されている間は、表示されているセルのみを更新することができます(ユーザーがビューからスクロールしなかったことを意味します)。
はここに、これまでに私のコードです:NSInvocationOperationの「カーネル」については
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleSubtitle
reuseIdentifier: CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.selectionStyle = UITableViewCellSelectionStyleGray;
}
// Configure the cell...
cell.textLabel.text = [[dbData objectAtIndex:indexPath.row] objectAtIndex:0];
cell.detailTextLabel.text = [[dbData objectAtIndex:indexPath.row] objectAtIndex:1];
NSString *ImageName = [[dbData objectAtIndex:indexPath.row] objectAtIndex:2];
NSString *cachedImageName = [[[ImageName stringByDeletingPathExtension] stringByAppendingString:thumbnailSizeSuffix] stringByAppendingPathExtension:@"png"];
NSString *cachedImagePath = [cachePath stringByAppendingPathComponent:cachedImageName];
if([[NSFileManager defaultManager] fileExistsAtPath:cachedImagePath])
cell.imageView.image = [UIImage imageWithContentsOfFile:cachedImagePath];
else
{
cell.imageView.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:defaultNeedsDownloadIconFile ofType:@"png"]];
NSArray *package = [NSArray arrayWithObjects:ImageName, cachedImagePath ,referencingTable, nil];
NSInvocationOperation *concurrentImageLoader = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(loadURI:) object:package];
[concurrentQueue addOperation: concurrentImageLoader];
[concurrentImageLoader release];
}
return cell;
}
、私はこれ試してみた:
- (void)loadURI:(id)package
{
NSArray *payload = (NSArray*)package;
NSString *imageName = [payload objectAtIndex:0];
NSString *cachedImagePath = [payload objectAtIndex:1];
NSString *imageURL = [NSString stringWithFormat:@"http://www.useanddisposeof.com/VentanaSurDB/%@/photo/%@",[payload objectAtIndex:2], imageName];
UIImage *newThumbnail = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]]];
if(!newThumbnail)
newThumbnail = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:defaultNotFoundIconFile ofType:@"png"]];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, thumbnailSize.width, thumbnailSize.height)];
imageView.layer.borderColor = [UIColor blackColor].CGColor;
imageView.layer.cornerRadius = 4.0;
imageView.layer.masksToBounds = YES;
imageView.layer.borderWidth = 1.0;
imageView.image = newThumbnail;
UIGraphicsBeginImageContext(CGSizeMake(thumbnailSize.width, thumbnailSize.height));
[imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
newThumbnail = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[imageView release];
[UIImagePNGRepresentation(newThumbnail) writeToFile:cachedImagePath atomically:YES];
[self performSelectorOnMainThread:@selector(updateCellImage) withObject:nil waitUntilDone:NO];
}
をそして、これはバックのためにメインスレッド内のコードですテーブルビューをリフレッシュする:
- (void)updateCellImage:(id)package
{
needReloadCachedImages = YES;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
// I know, I know, there's a race condition here.. I'll fix it if this code stays.
if(needReloadCachedImages)
[self.tableView reloadData];
needReloadCachedImages = NO;
}
アイデアをお持ちですか?
ああ私はそれを知らなかった。私は問題はそれがまだスクロールダウンが遅いということだと思う。ビューを更新しながらテーブルをスムーズにスクロールさせる方法があるのだろうかと思います。 – SaldaVonSchwartz