11

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 が応答さえ受け取らないことがわかりました。なぜこれが起こっているのかを突き止めようとしていますが、これまでのところ成功していません。何か見逃していたら教えてください。

4

5 に答える 5

9

更新された回答:

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

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

  2. 同時リクエストの数を妥当な数に制限するわけではありません。はい、NSURLConnectionリクエストの最大数が妥当な数になるまでリクエストを自動的に凍結しますが、最悪の場合、単に適切にキューに入れるのではなく、実際にリクエストがタイムアウトする可能性があります。

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

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

これを自分で修正しようとすると、すべてを正しくするには少し手間がかかります。しかし、これは、 (a) 同時リクエストを制限するために使用するLazyTableImages の表現です。NSOperationQueue(b) 当社がリクエストをキャンセルできるようにする。正直に言うと、上記のカテゴリの実装の方が優れていますが、上で列挙した欠陥を修正しながら、UIImageViewApple のオリジナルの構造を維持しようとしました。LazyTableImages

于 2013-01-18T14:58:12.280 に答える
8

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

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; 
}
于 2013-01-18T14:08:53.193 に答える
1

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

于 2013-01-18T14:44:51.557 に答える