web-dev-qa-db-ja.com

iOSの遅延-テーブル画像の読み込み

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が応答を受信しないことがわかりました。私はなぜこれが起こっているのかを調べようとしてきましたが、今のところ成功していません。何か足りないものがあったら教えてください。

11
Rameez Hussain

次の手順に従って、テーブルビューで遅延読み込みを実行できます。

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; 
}
8
Wolverine

更新された回答:

標準のApple LazyTableImages には、いくつかの欠陥があります。

  1. スクロールが終了するまで、画像を取得しようとはしません。彼らがそうすることを選んだ理由は理解していますが(おそらく、スクロールして離れる可能性のある画像を取得したくない)、これにより画像の表示が必要以上に遅くなります。

  2. 同時リクエストの数を妥当な数に制限することはありません。はい、NSURLConnectionは、リクエストの最大数が妥当な数になるまでリクエストを自動的にフリーズしますが、最悪のシナリオでは、単に適切にキューイングするのではなく、実際にリクエストをタイムアウトにすることができます。

  3. 画像のダウンロードを開始すると、セルが画面からスクロールアウトしても、画像はキャンセルされません。

簡単な修正は、IconDownloaderとすべてのスクロール/減速ロジックを廃止し、 UIImageView のいずれかからSDWebImageカテゴリを使用することです。または AFNetworking

これを自分で修正する場合、これをすべて正しく行うには少し作業が必要です。ただし、 これはLazyTableImages の表現であり、NSOperationQueueを使用して(a)同時リクエストを制限します。 (b)リクエストをキャンセルすることができます。私は上記のUIImageViewカテゴリの実装の方が良いと告白しますが、上記で列挙した欠陥を修正しながら、Appleの元のLazyTableImagesの構造を維持しようとしました。

9
Rob

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と一致するかどうかを確認する必要があります。

1
ahwulf

これはかなり遅い答えですが、iOSのバージョンが変更されると、アプローチは変わり続けます。

画像を遅延ロードするために、推奨されるアプローチは次のとおりです。

  1. すべての画像のURLをダウンロードして、コンテナ(配列/オブジェクトなど)に保存します
  2. バックグラウンドキューで非同期を実行する NSURLSessionTask (iOS 7以降のみ)を起動します。 iOS 7未満の場合は、 NSURLConnection SendAsynchronousRequest API を使用できます-iOS 9では非推奨になっているため、すぐに削除することをお勧めします。
  3. バックグラウンドキューにいる間に画像を作成する
  4. メインキューに戻り、正しいUITableViewCellを取得したことを確認してから、画像を更新します

ここで-全体のアプローチは 私のチュートリアルで説明されています

0
Nirav Bhatt

遅延ロードコントローラーを含むこのフレームワークを作成しました。使いやすく、箱から出してすぐに使用できます。 https://github.com/cloverstudio/CSUtils チュートリアルはここにあります: http://www.clover-studio.com/blog/using-csutils-ios-framework- for-lazy-loading-images /

0
Josip B.