2015-01-28 1 views
0

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

[cell.coverImage sd_setImageWithURL:[self.dataInJSONModel.Content[indexPath.row] CoverImage] placeholderImage:[UIImage imageNamed:@"imageplaceholder_general"]]; 

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

Поэтому я реализовал несколько изменений т.д .:

SDWebImageManager *manager = [SDWebImageManager sharedManager]; 
UIImageView * cellCoverImage = cell.coverImage; 
[manager downloadImageWithURL:[self.dataInJSONModel.Content[indexPath.row] CoverImage] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL * oriURL) { 

     NSArray *visibleIndexPaths = [tableView indexPathsForVisibleRows]; 
     if ([visibleIndexPaths containsObject:indexPath]) { 

      cellCoverImage.image = image; 
     } 
    }]; 

Или даже сравнить URL-адреса:

SDWebImageManager *manager = [SDWebImageManager sharedManager]; 
UIImageView * cellCoverImage = cell.coverImage; 
[manager downloadImageWithURL:[self.dataInJSONModel.Content[indexPath.row] CoverImage] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL * oriURL) { 

    if([oriURL isEqual:[self.dataInJSONModel.Content[indexPath.row] CoverImage]]) 
    { 
     cell.coverImage.image = image; 

    } 

}]; 

Тем не менее проблема сохраняется. Или я, возможно, неправильно запрограммировал его? Нашел несколько предложений в Интернете, но конкретного решения пока не видели.

Нужна помощь!

EDIT

Я уже сделал некоторые изменения к нему, но по-прежнему не работает:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 

NewsFeedCell * cell = [tableView dequeueReusableCellWithIdentifier:@"NewsFeedCell" forIndexPath:indexPath]; 


if (self.dataInJSONModel) 
{ 
    cell.coverImage.image = nil; 
    SDWebImageManager *manager = [SDWebImageManager sharedManager]; 
    [manager downloadImageWithURL:[self.dataInJSONModel.Content[indexPath.row] CoverImage] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL * oriURL) { 

     if ([cell isEqual:[self.tableView cellForRowAtIndexPath:indexPath]]) 
     { 
      cell.coverImage.image = image; 
     } 

    }]; 

} 
+0

Может ли вы показать коды в вашем методе cellForRowAtIndexPath ? –

+0

@UlasSancak My cellForRowAtIndexPath как выше. – Marcus

+0

Прежде всего вернитесь к методу sd_setImageWithURL. Он должен работать. Проблема не в этом. Вы используете xib для ячейки или это прототип ячейки? –

ответ

0

Вы правы в вашем анализе проблемы, просто не выполнил его совершенно правильно.

некоторые псевдокод cellForRowAtIndexPath ...

- set the cell.imageView.image to nil to wipe out 
       previous use of cell image view contents 
- get the URL from data source 
- initiate asynchronous download with completion ^{ 
     //check the cell is still the correct cell 
     if ([cell isEqual: [collectionView cellForRowAtIndexPath:indexPath]]) { 
      cell.imageView.image = image 
     } 
} 

Несколько вещей, которые вы делаете неправильно
- не захватить ссылку зрения изображения ячейки, пока вы не знаете, вам это нужно (в завершении block)
- не проверяйте visibleIndexPaths, indexPath все еще может быть видимым, но назначается другой ячейке (если вы снова прокрутили, а затем снова включили). Техника «cell isEqual», которую я использую здесь, должна быть достаточной для всех случаев.

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

+0

Я внес изменения, как вы упомянули (см. EDIT выше), но все еще не работает. Или я неправильно закодировал? Благодаря! – Marcus

+0

'cell.coverImage = nil' должно быть' cell.coverImage.image = nil' – foundry

+0

Изменено. Но все равно не работает. Некоторые изображения даже пропали без вести после прокрутки. – Marcus

0

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

Простым решением является;

dispatch_async(dispatch_get_main_queue(), ^{ 
     cell.coverImage.image = image; 
    }); 

Кроме того, если вы собираетесь ссылаться на Tableview в вашем блоке завершения, вы должны использовать слабую ссылку на него.

+0

Изменено в соответствии с вашим предложением, но все равно не работает. – Marcus

2

Опубликован вопрос на странице SDWebImage Github и получил предложение от кого-то, кто решает мою проблему! Я просто переопределяю метод prepareForReuse в файле реализации моей ячейки и уменьшаю изображение обращенного изображения.

Пример кода для будущего читателя:

In my NewsFeedCell.m 
- (void) prepareForReuse 
{ 
    [super prepareForReuse]; 

    self.coverImage.image = NULL; 

} 

И это решает эту проблему! Моя открытая проблема в GitHub - https://github.com/rs/SDWebImage/issues/1024, если кто-то из вас захочет посмотреть.

+0

работает как шарм –

2

Я столкнулся с той же проблемой и попытался назначить .image = nil, но не работать.

Наконец, мой sloution должны переопределить prepareForReuse в UITableViewCell с отменить операцию:

- (void)prepareForReuse 
{ 
    [super prepareForReuse]; 
    [_imageView sd_cancelCurrentImageLoad]; 
} 
0

я пытался большинство из этих решений, провел некоторое время на исправление этого. У меня есть 2 решения для меня.

  • При установке изображения в ImageView в ячейках остановить загрузку.

В cellForRow добавить следующее:

cell.imageView.sd_cancelCurrentImageLoad() 

, а затем в ячейке:

func prepareForReuse() { 
    imageView.image = UIImage.placeholderImage() // or nill 
} 

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

  • Another более элегантных решений является добавление расширения для UIImageView:

Выберите анимацию, которая вам подходит, и попробовать это:

func setImageAnimated(imageUrl:URL, placeholderImage:UIImage) { 
    self.sd_setImage(with: imageUrl, placeholderImage: placeholderImage , options:SDWebImageOptions.avoidAutoSetImage, completed: { (image, error, cacheType, url) in 
     if cacheType == SDImageCacheType.none { 
      UIView.transition(with: self.superview!, duration: 0.2, options: [.transitionCrossDissolve ,.allowUserInteraction, .curveEaseIn], animations: { 
       self.image = image 
      }, completion: { (completed) in 
      }) 
     } else { 
      self.image = image 
     } 
    }) 
}