2014-02-02 2 views
2

Моя цель - установить текст, затем сделать асинхронный вызов для изображения и установить изображение по прибытии.UITableView asynchronous UIImage setting

Я в настоящее время сделать асинхронный вызов для изображений, чтобы установить в UITableViewCell, и заметили мою предыдущую технику привел в петле я недавно идентифицированный:

 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    UITableViewCell* cell = [_tableView dequeueReusableCellWithIdentifier:@"id"]; 

    if (cell == nil) { 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"id"]; 
    } 

    [NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:userAvatar]] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { 
     if (data) { 
      UIImage* avatarImage = [UIImage imageWithData:data]; 
      if (avatarImage) { 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        [cell.imageView setImage:avatarImage]; 
       }); 


       /* 
       .--.  [STOP] 
      .----' '--. | 
      '-()-----()-' | 

      If I include the following, 
      the program goes in a loop, 
      and have not readily identified workaround: 

       dispatch_async(dispatch_get_main_queue(), ^{ 
        [_tableView reloadData]; 
       }); 

          [GO]   .--. 
          |   .----' '--. 
          |   '-()-----()-' 

       */ 
      } 
     } 
    }]; 

    cell.textLabel.text = @"foo"; 
    cell.detailTextLabel.text = @"bar"; 
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 


    return cell; 
} 

Есть ли методика для получения результата я ищу без пользовательский сеттер в пользовательском классе?

+6

Не называть 'reloadData' из' cellForRow ...'. Плохие вещи случаются. Посмотрите пример приложения Apple LazyTableImages, чтобы посмотреть, как это сделать. – rmaddy

+1

Вы также можете использовать AFNetworking, чтобы сделать это легко - проверьте дополнения UIImageView + AFNetworking.h. – joao

+0

@joao AFNetworking использует очень упрощенный подход, который в основном «заставляет его работать», но на самом деле представляет более серьезную проблему. Поэтому я бы не рекомендовал его. – CouchDeveloper

ответ

2

Вы определенно не хотите вызывать -reloadData каждый раз, когда вы загружаете изображение, это слишком тяжело, а также вызывает перезагрузку всех ячеек, что вызывает этот метод, как вы обнаружили.

Я не ясно, почему вы хотите позвонить -reloadData вообще, потому что это уже должно работать как есть устанавливающее изображение на ImageView клетки заставит дисплей обновить ... КРОМЕ:

В этом коде есть большая логическая ошибка, потому что ячейки повторно используются все время, но вы асинхронно загружаете изображение, а затем устанавливаете его в определенную ячейку. Нет гарантии, что ячейка по-прежнему будет привязана к той же строке таблицы к моменту загрузки изображения - вы просто устанавливаете изображение в случайной ячейке в этой точке.

В целом, tableViews создает только достаточное количество ячеек, которые могут быть видны на экране одновременно, а не по одному в строке таблицы. По мере прокрутки вниз по таблице ячейки сверху удаляются и повторно используются ниже, чтобы сохранить память и время создания.

Вместо того, чтобы напрямую устанавливать изображение на ячейку, снова найдите ячейку в таблицеView по ее строке (если она все еще видна) и установите ее таким образом.

Кроме того, вы не кэшируете полученные изображения, что приведет к новой выборке каждый раз, когда пользователь прокручивается вниз и затем снова поднимается. Хотя встроенный сетевой код будет выполнять некоторый уровень кэширования, вы никогда не знаете, сколько он есть, и, конечно же, не так быстро менять HTTP-запросы на полные изображения, поэтому вы хотите сами кэшировать эти изображения, связанные с исходными URL-адресами или строки или любые ключи однозначно идентифицируют их.

Смежные вопросы