2015-03-17 2 views
0

У меня есть табличный вид с пользовательскими ячейками. Каждая ячейка имеет изображение, заголовок и описание. Когда я впервые загружаю таблицу, она загружается отлично. если я медленно прокручиваю изображение, также, похоже, работает нормально. Как только я быстро прокручиваю (при условии, что количество ячеек достаточно велико, чтобы не вписываться без прокрутки вверх и вниз), изображения начинают изменять ячейки в случайном порядке. Некоторые ячейки имеют одинаковое изображение дважды.Пользовательские изображения сот меняются самостоятельно в UITableView

Любая подсказка, почему это происходит?

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

    NewsArticle *currArt = [self.lN_Dept objectAtIndex:indexPath.row]; 

    if(currArt.artImage == Nil) 
    { 
     if([currArt.mainImage_URL rangeOfString:@"<img src="].location != NSNotFound) 
     { 
      NSRange range = [currArt.mainImage_URL rangeOfString:@"<img src=\"/CONC/"]; 
      NSString *substring = [[currArt.mainImage_URL substringFromIndex:NSMaxRange(range)] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; 

      NSRange range2 = [substring rangeOfString:@"\""]; 
      NSString *substring2 = [[substring substringToIndex:NSMaxRange(range2)-1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; 

      NSString *imageURL = [PUB_URL stringByAppendingString:substring2]; 

      [self downloadImageWithURL:[NSURL URLWithString:imageURL] completionBlock:^(BOOL succeeded, UIImage *image) { 
       if (succeeded) { 
        currArt.artImage = image; 
        cell.ArtDisplayImage.image = currArt.artImage; 
       } 
      }]; 
     } 
    } 
    else 
    { 
     cell.ArtDisplayImage.image = currArt.artImage; 
    } 
    [cell configureCellForEntry:currArticle]; 
    return cell; 
} 


- (void)downloadImageWithURL:(NSURL *)url completionBlock:(void (^)(BOOL succeeded, UIImage *image))completionBlock 
{ 
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 
    [NSURLConnection sendAsynchronousRequest:request 
            queue:[NSOperationQueue mainQueue] 
         completionHandler:^(NSURLResponse *response, NSData *Data, NSError *error) { 
          if (!error) 
          { 
           UIImage *image = [[UIImage alloc] initWithData:Data]; 
           completionBlock(YES,image); 
          } else{ 
           completionBlock(NO,nil); 
          } 
         }]; 
} 
+0

Посмотрите мой ответ здесь: http://stackoverflow.com/questions/7852033/gcd-uitableview-asynchronous-load-images-wrong-cells-are -loaded-to-new-image/7852138 # 7852138 – hypercrypt

+0

@hypercrypt Не могли бы вы привести пример, как бы вы сделали это с помощью кода выше? – dan

ответ

1

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

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

Еще одна вещь, которую вы можете сделать, это сохранить в ячейке URL-адрес, который он пытается загрузить, и сравнить URL-адрес полученной загрузки с сохраненным URL-адресом ячейки, чтобы узнать, остались ли они одинаковыми (и установите только изображение, если они все те же).

Что-то вроде этого следует сделать это:

if(currArt.artImage == Nil) 
{ 
    if([currArt.mainImage_URL rangeOfString:@"<img src="].location != NSNotFound) 
    { 
     NSRange range = [currArt.mainImage_URL rangeOfString:@"<img src=\"/CONC/"]; 
     NSString *substring = [[currArt.mainImage_URL substringFromIndex:NSMaxRange(range)] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; 

     NSRange range2 = [substring rangeOfString:@"\""]; 
     NSString *substring2 = [[substring substringToIndex:NSMaxRange(range2)-1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; 

     NSString *imageURL = [PUB_URL stringByAppendingString:substring2]; 
     cell.imageURL = imageURL; // you need to add an imageURL string property to your cells 
     // you need to return the URL string in your block to compare it 
     [self downloadImageWithURL:[NSURL URLWithString:imageURL] completionBlock:^(BOOL succeeded, UIImage *image, NSString *url) 
     { 
      if (succeeded) 
      { 
       currArt.artImage = image; 
       if(cell.imageURL isEqualToString:url]) 
       { 
        cell.ArtDisplayImage.image = currArt.artImage; 
       } 
      } 
     }]; 
    } 
} 
else 
{ 
    cell.ArtDisplayImage.image = currArt.artImage; 
    cell.imageURL = nil; // make sure it is not overwritten 
} 
+0

Я добавил еще одну функцию на свой пост. не могли бы вы рассказать мне, как изменить это, чтобы он сделал то, что вы предложили. сравнить URL. спасибо – dan

2

Это происходит потому, что вы понимаете, как UITableView работы. Представим, что в вашем представлении таблицы есть 100 ячеек, и он может отображать 10 ячеек одновременно. При загрузке табличного представления он создает 10 экземпляров ваших ячеек. Когда вы начинаете прокрутку вниз по представлению таблицы, на самом деле не создаются новые экземпляры ваших ячеек - он повторно использует ячейки, которые исчезли с экрана (потому что вы вызываете [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];). Это означает, что ячейка с индексом 10 будет иметь ту же ссылку, что ячейка с индексом 0.
Возвращаясь к вашему вопросу, который вы загружаете изображения с

[self downloadImageWithURL:[NSURL URLWithString:imageURL] completionBlock:^(BOOL succeeded, UIImage *image) { 
      if (succeeded) { 
       currArt.artImage = image; 
       cell.ArtDisplayImage.image = currArt.artImage; 
      } 
}]; 

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

+0

Как вы предлагаете мне отменить загрузку изображения для ячеек, которые исчезли с экрана? – dan

1

Так что-то вроде этого:

[self downloadImageWithURL:[NSURL URLWithString:imageURL] completionBlock:^(BOOL succeeded, UIImage *image) { 
      if (succeeded) { 

       YourCellType *cellToUpdate = [tableView cellForIndexPath:indexPath]; 
       if (cellToUpdate) 
       { 
        currArt.artImage = image; 
        cellToUpdate.ArtDisplayImage.image = currArt.artImage; 
       } 
      } 
     }]; 
Смежные вопросы