将UIViews添加到cell.contentView时出现UITableView性能问题

时间:2013-05-03 19:56:09

标签: iphone ios objective-c uitableview

我在UITableViewCells上使用某些子视图时遇到了性能问题。在我继续滚动之后,它最终开始变得很慢。

我正在做的第一步是为每个单元格创建一个公共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;
}

当我将缩略图视图添加到单元格时,性能问题似乎是因为当我评论该行时,我似乎没有它。缩略图信息是动态的,并将随每个单元格而变化。对于如何在不降低性能的情况下执行此操作,我将不胜感激。

3 个答案:

答案 0 :(得分:5)

每次单元格进入视图时,

UITableView都会调用tableView:cellForRowAtIndexPath:dequeueReusableCellWithIdentifier:将重用现有单元格对象(如果可用)。这两个事实相结合,使您进入一个场景,每次滚动时,相同数量的单元格对象最终会有越来越多的子视图。

正确的方法是创建一个具有UITableViewCell属性的自定义thumbnailView子类。在该属性的setter中,删除先前的缩略图(如果有),然后将新的缩略图添加到contentView。这样可以确保您在任何时候都只有一个缩略图子视图。

不太理想的方法是向UIViewNewsItemThumbnailView)返回的thumbNailMainView.tag = someIntegerConstant添加标记,然后搜索包含该标记的任何视图,并在添加其他视图之前将其删除:< / p>

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

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

答案 1 :(得分: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;
}

答案 2 :(得分: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];

希望它对你有所帮助。