Apple here )の例を使用して、アプリに画像の遅延読み込みを正常に実装しました。つまり、画像をそのまま読み込みたいということです。スクロールしますが、ドラッグが終了したときにのみ画像がセルに読み込まれます(画面から指を離します。それまではセルは空のままです)。コードを次のように変更しました。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//NSLog(@"cell for row at indexpath, size - %f, current - %d", flowTable.contentSize.height, self.current);
NSString *CellIdentifier = @"FlowCell";
MyFlowCell *cell = (MyFlowCell *)[self.flowTable dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"FlowCell" owner:nil options:nil];
// cell = [nib objectAtIndex:0];
for(id currentObject in nib)
{
if([currentObject isKindOfClass:[MyFlowCell class]])
{
cell = (MyFlowCell *)currentObject;
break;
}
}
}
ImageDetails *rowItem = [self.imageData objectAtIndex:indexPath.row];
if (!rowItem.mainImage)
{
// if (self.flowTable.dragging == NO && self.flowTable.decelerating == NO)
// {
[self startIconDownload:rowItem forIndexPath:indexPath];
//}
cell.mainImage.backgroundColor = [UIColor grayColor];
}
else
{
cell.mainImage.image = rowItem.mainImage;
}
}
return cell;
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (!decelerate)
{
// [self loadImagesForOnscreenRows];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
//[self loadImagesForOnscreenRows];
}
さらに、ImageDownloaderクラスでは、画面から指を離すまでNSURLConnectionが応答を受信しないことがわかりました。私はなぜこれが起こっているのかを調べようとしてきましたが、今のところ成功していません。何か足りないものがあったら教えてください。
次の手順に従って、テーブルビューで遅延読み込みを実行できます。
Class.hに、次のように入力します。
NSMutableDictionary *Dict_name;
BOOL isDragging_msg, isDecliring_msg;
Class.mファイルで、次のコードを表示します。
Dict_name = [[NSMutableDictionary alloc] init];
CellForRowAtIndexPath内:
if ([dicImages_msg valueForKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:@"image name or image link"]]) {
cell.image_profile.image=[dicImages_msg valueForKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:@"image name or image link"]];
}
else
{
if (!isDragging_msg && !isDecliring_msg)
{
[dicImages_msg setObject:[UIImage imageNamed:@"Placeholder.png"] forKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:@"image name or image link"]];
[self performSelectorInBackground:@selector(downloadImage_3:) withObject:indexPath];
}
else
{
cell.image_profile.image=[UIImage imageNamed:@"Placeholder.png"];
}
}
ダウンロード画像の場合、機能は次のとおりです。
-(void)downloadImage_3:(NSIndexPath *)path{
NSAutoreleasePool *pl = [[NSAutoreleasePool alloc] init];
NSString *str=[here Your image link for download];
UIImage *img = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:str]]];
[dicImages_msg setObject:img forKey:[[msg_array objectAtIndex:path.row] valueForKey:@"image name or image link same as cell for row"]];
[tableview performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
[pl release];
}
そして最後に、これらのメソッドをクラスに入れます。
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
isDragging_msg = FALSE;
[tableview reloadData];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
isDecliring_msg = FALSE;
[tableview reloadData];
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
isDragging_msg = TRUE;
}
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView{
isDecliring_msg = TRUE;
}
更新された回答:
標準のApple LazyTableImages には、いくつかの欠陥があります。
スクロールが終了するまで、画像を取得しようとはしません。彼らがそうすることを選んだ理由は理解していますが(おそらく、スクロールして離れる可能性のある画像を取得したくない)、これにより画像の表示が必要以上に遅くなります。
同時リクエストの数を妥当な数に制限することはありません。はい、NSURLConnection
は、リクエストの最大数が妥当な数になるまでリクエストを自動的にフリーズしますが、最悪のシナリオでは、単に適切にキューイングするのではなく、実際にリクエストをタイムアウトにすることができます。
画像のダウンロードを開始すると、セルが画面からスクロールアウトしても、画像はキャンセルされません。
簡単な修正は、IconDownloader
とすべてのスクロール/減速ロジックを廃止し、 UIImageView
のいずれかからSDWebImage
カテゴリを使用することです。または AFNetworking
。
これを自分で修正する場合、これをすべて正しく行うには少し作業が必要です。ただし、 これはLazyTableImages の表現であり、NSOperationQueue
を使用して(a)同時リクエストを制限します。 (b)リクエストをキャンセルすることができます。私は上記のUIImageView
カテゴリの実装の方が良いと告白しますが、上記で列挙した欠陥を修正しながら、Appleの元のLazyTableImages
の構造を維持しようとしました。
UITableViewCellに画像のurlプロパティとUIImageプロパティ(およびキューのプロパティまたは静的値)があると仮定します。
- (void) setThumbnailUrlString:(NSString *)urlString
{
thumbnailUrlString = urlString;
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
if ( queue == nil )
{
queue = [[NSOperationQueue alloc] init];
}
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse * resp, NSData *data, NSError *error)
{
dispatch_async(dispatch_get_main_queue(),^
{
if ( error == nil && data )
{
UIImage *urlImage = [[UIImage alloc] initWithData:data];
thumbnail.image = urlImage;
}
});
}];
}
実装の問題は、画像の読み込み方法がおそらくメインスレッドで発生していることです。イメージを非同期でロードしてから、メインスレッドでイメージを更新する必要があります。
正しくするには、セルの画像が別の画像に再利用される前にセルの画像の読み込みが遅すぎる場合、ブロックは応答のURLが要求されたURLと一致するかどうかを確認する必要があります。
これはかなり遅い答えですが、iOSのバージョンが変更されると、アプローチは変わり続けます。
画像を遅延ロードするために、推奨されるアプローチは次のとおりです。
ここで-全体のアプローチは 私のチュートリアルで説明されています 。
遅延ロードコントローラーを含むこのフレームワークを作成しました。使いやすく、箱から出してすぐに使用できます。 https://github.com/cloverstudio/CSUtils チュートリアルはここにあります: http://www.clover-studio.com/blog/using-csutils-ios-framework- for-lazy-loading-images /