1

私はSOとWebを見回しましたが、具体的な答えは見つかりませんでした。

簡単に言うと、Flickrから画像情報を読み込んでいるテーブルがあります。各セルの左側に画像のサムネイルを表示したい。

メイン(UI)スレッドをブロックせずにこれを行うために、私はブロックを使用しています:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  static NSString *CellIdentifier = @"top50places";
  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

  //getting the selected row image 
  NSDictionary* currentImageDictionary=[self.topfifty objectAtIndex:indexPath.row];//topFifty is an array of image dictionaries


  //creating the download queue 
  dispatch_queue_t downloadQueue=dispatch_queue_create("thumbnailImage", NULL);

  dispatch_async(downloadQueue, ^{

    UIImage *downloadedThumbImage=[self getImage:currentImageDictionary] ;

    //Need to go back to the main thread since this is UI related
    dispatch_async(dispatch_get_main_queue(), ^{

        cell.imageView.image = downloadedThumbImage ;

    });

  });

  dispatch_release(downloadQueue);

  return cell;

}

今、これは機能しません。ブロックを実行する前にセルを返す可能性が高いためです。しかし同時に、ブロックがreturn引数を受け入れないため、メインキューブロック内のセルを返すことができません。

UITableViewCellサブクラスの作成を避けたい。

ブロックを使用した簡単な答えはありますか?

ありがとうKMB

4

1 に答える 1

5

問題cell.imageView.image = downloadedThumbImage;は、このセルが再利用されて別の行に使用される可能性があることです。

代わりに、特定の indexPath の現在のセルを更新する必要があります (indexPath は同じになります)。

UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.imageView.image = image;  

または、モデルを更新してから、特定の indexPath でセルをリロードすることもあります。

myModel.image = downloadedThumbImage;
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                                      withRowAnimation:UITableViewRowAnimationNone];  


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  static NSString *CellIdentifier = @"top50places";
  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

  //getting the selected row image 
  NSDictionary* currentImageDictionary=[self.topfifty objectAtIndex:indexPath.row];//topFifty is an array of image dictionaries

  UIImage *currentImage = [currentImageDictionary objectForKey:@"image"];

  if (currentImage) { 
      // we already fetched the image, so we just set it to the cell's image view
      cell.imageView.image = currentImage;
  }
  else {
      // we don't have the image, so we need to fetch it from the server  

      // In the meantime, we can set some place holder image
      UIImage *palceholderImage = [UIImage imageNamed:@"placeholder.png"];
      cell.imageView.image = palceholderImage;

      // set the placeholder as the current image to your model, so you won't 
      // download the image multiple times (can happen if you reload this cell while 
      // download is in progress)
      [currentImageDictionary setObject:palceholderImage forKey:@"image"];

      // then download the image
      // creating the download queue 
      dispatch_queue_t downloadQueue=dispatch_queue_create("thumbnailImage", NULL);

      dispatch_async(downloadQueue, ^{
         UIImage *downloadedThumbImage=[self getImage:currentImageDictionary] ;

         //Need to go back to the main thread since this is UI related
         dispatch_async(dispatch_get_main_queue(), ^{
                // store the downloaded image in your model
                [currentImageDictionary setObject:image forKey:@"image"];

                // update UI
                UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
                cell.imageView.image = image;    
         });
      });
      dispatch_release(downloadQueue);
  }

  return cell;
}
于 2012-08-09T13:16:35.837 に答える