2013-05-03 3 views
4

У меня возникают проблемы с производительностью при использовании некоторых подзонов на моем UITableViewCells. После того, как я продолжаю прокручивать, он в конце концов начинает становиться очень медленным.Проблемы с производительностью UITableView при добавлении UIViews в cell.contentView

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

enter image description here

Вот код, я использую, чтобы сделать это:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
     static NSString *NewsCellIdentifer = @"NewsCellIdentifier"; 


     NewsItem *item = [self.newsArray objectAtIndex:indexPath.row]; 


      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:NewsCellIdentifer]; 

      if (cell == nil) 
      { 
       cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NewsCellIdentifer]; 


       cell.contentView.backgroundColor = [UIColor clearColor]; 

       UIView *whiteRoundedCornerView = [[UIView alloc] initWithFrame:CGRectMake(10,10,300,100)]; 
       whiteRoundedCornerView.backgroundColor = [UIColor whiteColor]; 
       whiteRoundedCornerView.layer.masksToBounds = NO; 
       whiteRoundedCornerView.layer.cornerRadius = 3.0; 
       whiteRoundedCornerView.layer.shadowOffset = CGSizeMake(-1, 1); 
       whiteRoundedCornerView.layer.shadowOpacity = 0.5; 

       [cell.contentView addSubview:whiteRoundedCornerView]; 
       [cell.contentView sendSubviewToBack:whiteRoundedCornerView]; 

       cell.layer.shouldRasterize = YES; 
       cell.layer.rasterizationScale = [UIScreen mainScreen].scale; 
       cell.layer.opaque = YES; 

       cell.opaque = YES;  
      } 

      [cell.contentView addSubview:[self NewsItemThumbnailView:item]]; 

      return cell; 
} 

Вот метод, который возвращает вид эскизов графики и текста:

- (UIView *) NewsItemThumbnailView:(NewsItem *)item 
{ 
    UIView *thumbNailMainView = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 50, 70)]; 
    UIImageView *thumbNail = [[UIImageView alloc] initWithImage:[UIImage imageNamed:item.ThumbNailFileName]]; 
    thumbNail.frame = CGRectMake(10,10, 45, 45); 
    UILabel *date = [[UILabel alloc] init]; 
    date.frame = CGRectMake(10, 53, 45, 12); 
    date.text = item.ShortDateString; 
    date.textAlignment = NSTextAlignmentCenter; 
    date.textColor = [BVColors WebDarkGrey]; 
    CGFloat fontSize = 10.0; 
    date.font = [BVFont Museo:&fontSize]; 

    date.opaque = YES; 
    thumbNail.opaque = YES; 
    thumbNailMainView.opaque = YES; 


    [thumbNailMainView addSubview:thumbNail]; 
    [thumbNailMainView addSubview:date]; 

    return thumbNailMainView; 
} 

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

+1

Добавляя subview каждый раз, когда этот код называется, вы выращиваете коллекцию подпрограмм в UITableViewCell. Функция dequeing создает новую ячейку представления таблицы или захватывает существующую. Как только он начнет захватывать существующие ячейки, вы добавляете надпись UIImageView существующего UIImageView. В результате вы будете экспоненциально увеличивать UIImageView, которые должны отображаться для каждой ячейки. Это существенно замедлит ваше приложение. Мне нравится jszumski ответ ниже. – Rob

ответ

2

Я в конечном итоге используя решение, найденное на этом StackOverflow сообщение:

How should I addSubview to cell.contentView?

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *NewsCellIdentifer = @"NewsCellIdentifier"; 

    NewsItem *item = [self.newsArray objectAtIndex:indexPath.row]; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:NewsCellIdentifer]; 


    UIView *thumbNailMainView = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 50, 70)]; 
    UIImageView *thumbNail; 

    UIView *textMainView = [[UIView alloc] initWithFrame:CGRectMake(20,20,80,80)]; 
    UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(52,-5, 70, 20)]; 
    UILabel *teaserLabel = [[UILabel alloc] initWithFrame:CGRectMake(50,20, 210, 40)]; 

    UIView *newsItemCornerMainView = [[UIView alloc] initWithFrame:CGRectMake(255.7, 55.2, 55, 55)]; 
    UIImageView *cornerIconView; 

    // If the cell doesn't existing go ahead and make it fresh. 
    if (cell == nil) 
    { 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NewsCellIdentifer]; 


     // Configure all the various subviews 

     ..... //Sample below 

     // Make the title view 
     headerLabel.text = item.Title; 
     CGFloat textfontSize = 16.0f; 
     headerLabel.font = [BVFont Museo:&textfontSize]; 
     headerLabel.textColor = [BVColors WebBlue]; 
     headerLabel.textAlignment = NSTextAlignmentLeft; 
     headerLabel.numberOfLines = 0; 
     headerLabel.tag = 50; 
     // Make the Teaser view 
     teaserLabel.text = item.Teaser; 
     teaserLabel.numberOfLines = 0; 
     CGFloat tfontSize = 13.0f; 
     teaserLabel.textAlignment = NSTextAlignmentLeft; 
     teaserLabel.textColor = [BVColors WebDarkGrey]; 
     teaserLabel.font = [BVFont HelveticaNeue:&tfontSize]; 
     [teaserLabel sizeToFit]; 
     teaserLabel.tag = 51; 
     [textMainView addSubview:headerLabel]; 
     [textMainView sendSubviewToBack:headerLabel]; 
     [textMainView addSubview:teaserLabel]; 
     [cell.contentView addSubview:textMainView]; 

     .... 
    } 

    thumbNail = (UIImageView *) [cell viewWithTag:47]; 
    [thumbNail setImage:[UIImage imageNamed:item.ThumbNailFileName]]; 

    headerLabel = (UILabel *) [cell viewWithTag:50]; 
    headerLabel.text = item.Title; 
    teaserLabel = (UILabel *) [cell viewWithTag:51]; 
    teaserLabel.text = item.Teaser; 

    cornerIconView = (UIImageView *) [cell viewWithTag:48]; 
    [cornerIconView setImage:[UIImage imageNamed:item.CornerIconFileName]]; 

    return cell; 
} 
1

Вы должны изменять только контент thumbNailMainView, но вы не должны добавлять его содержимое в ячейку каждый раз.

Так добавьте эту строку, где вы выделяющий клетку

[cell.contentView addSubview:[self NewsItemThumbnailView:item]]; 

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

Назначь тег thumbNailMainView и его подтаблица thumbNail затем получить доступ к нему, как

UIView *_thumbNailMainView = [cell.contentView viewWithTag:_thumbNailMainView_tag]; 
UIImageView *_thumbNail = [_thumbNailMainView viewWithTag:thumbNail_tag]; 
_thumbNail.image = [UIImage imageNamed:item.ThumbNailFileName]; 

Надеется, что это помогает.

+0

Спасибо, это было полезно для того, чтобы привести меня к окончательному решению! – Flea

+0

Больше всего приветствуются. Отметьте это, если это вам поможет. –

5

UITableView будет вызывать tableView:cellForRowAtIndexPath: каждый раз, когда ячейка появляется в поле зрения, а dequeueReusableCellWithIdentifier: будет повторно использовать существующие объекты ячеек, если они доступны. Эти два факта объединяют вас в сценарий, где каждый раз, когда вы прокручиваете, одно и то же конечное число объектов ячейки заканчивается увеличением числа подзонов.

Правильный подход заключается в создании пользовательского подкласса UITableViewCell, который имеет свойство для thumbnailView. В установщике для этого свойства удалите предыдущую миниатюру (если есть), а затем добавьте новую в contentView. Это гарантирует, что в любой момент вы будете иметь только один просмотр эскизов.

Менее оптимальный подход будет добавление тега к UIView вернулся из NewsItemThumbnailView (thumbNailMainView.tag = someIntegerConstant), а затем искать для любого вида с этим тегом и удалить его, прежде чем добавить еще один:

// remove old view 
UIView *oldThumbnailView = [cell.contentView viewWithTag:someIntegerConstant]; 
[oldThumbnailView removeFromSuperview]; 

// add new view 
[cell.contentView addSubview:[self NewsItemThumbnailView:item]]; 
+0

Спасибо, это было полезно для того, чтобы привести меня к окончательному решению! – Flea

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