使用Custom UITableViewCells提高ViewController的加载速度(破纪录)

时间:2012-09-11 00:26:07

标签: ios ios5 uitableview

我有一个带有UITableView的UIViewController加载得非常慢(可能是糖蜜慢)我可以告诉它是由于在ViewController拥有的分组UITableview中为UITableViewCells设置自定义背景图像。

我认为我正在关注其他SO问题中提到的建议: Tricks for improving iPhone UITableView scrolling performance

我也遵循了这篇文章,以确保我没有做一些愚蠢的事情: Cocoa With Love Custom UITableView Drawing

一旦我不调用后台样式代码,性能就会提高。

根据建议,我正在执行所有这些步骤:

  
      
  • 由于设计的方式,我有2种不同的细胞变化,并且不能具有统一的行高。无论细胞变化如何,行背景总是3个图像中的1个并且基于行索引。 0:top_row_image,n-1:bottom_row_image,所有其他:middle_row_image
  •   
  • 我在ViewController的viewDidLoad中加载用于背景的图像。
  •   
  • 我没有任何drawRect代码,因为我让单元格中的UITextField处理
  •   
  • Cell的图层设置为opaque
  •   
  • 正在重复使用单元标识符
  •   
  • 未从NIB文件加载单元格
  •   

基本上,我想根据表格的行类型,为每个表格的部分行设置不同的顶部,中间和底部行背景图像。任何人都可以建议在UITableView上使用自定义背景的更好方法吗?

这是我的代码:

ViewController:
@property (nonatomic, weak) IBOutlet                            *tableview;
@property (nonatomic, strong, readwrite) UIImage                *topRowImage;
@property (nonatomic, strong, readwrite) UIImage                *middleRowImage;
@property (nonatomic, strong, readwrite) UIImage                *bottomRowImage;

@synthesize tableview = _tableview;    
@synthesize topRowImage = _topRowImage;         
@synthesize middleRowImage = _middleRowImage;
@synthesize bottomRowImage = _bottomRowImage;

// Load the images that will be used for the cell background ahead of time
- (void)viewDidLoad
{
    [super viewDidLoad];        

    // All of the images are 60x20 but my cells are 300x44 or 300x56
    UIEdgeInsets edgeInsets = UIEdgeInsetsMake(2, 4, 2, 4);        
    self.topRowImage = [[UIImage imageNamed:@"top_row.png"] resizableImageWithCapInsets:edgeInsets];        

    UIEdgeInsets edgeInsets = UIEdgeInsetsMake(0, 4, 0, 4);
    self.middleRowImage = [[UIImage imageNamed:@"middle_row.png"] resizableImageWithCapInsets:edgeInsets];            

    edgeInsets = UIEdgeInsetsMake(2, 4, 2, 4);
    self.bottomRowImage = [[UIImage imageNamed:@"bottom_row.png"] resizableImageWithCapInsets:edgeInsets];    
}

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellId = [self getCellIdAt:indexPath];

    BaseCustomTableViewCell *cell = (BaseCustomTableViewCell *)[aTableView dequeueReusableCellWithIdentifier:cellId];

    if (cell == nil) 
    {
        if ([cellId isEqualToString:@"CellId1"])
        {
           cell = [[CustomTableViewCell1 alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];     
        }
        else
        { 
           cell = [[CustomTableViewCell2 alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];     
        }
    }

    // the following line seems to be the bottleneck
    [self styleBackground:cell indexPath:indexPath totalRows:totalRows];

    [cell configureData:myRowData];
}

- (void)styleCellBackground:(BaseCustomTableViewCell *)cell 
                  indexPath:(NSIndexPath *)indexPath
                  totalRows:(NSInteger)totalRows
{
    UIImage *backgroundImage = nil;    

    if (indexPath.row == 0)
    {
        // Top row of this section        
        backgroundImage = self.topRowImage; // ivar loaded during 'viewDidLoad'
    }
    else if (indexPath.row == totalRows - 1)
    {
        // Bottom row of this section        
        backgroundImage = self.bottomRowImage;
    }
    else {
        // Middle row of this section        
        backgroundImage = self.middleRowImage;
    }

    [cell updateRowBackground:backgroundImage];
}

@implementation CustomTableViewCell

-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])
    {        
        // Create my text field
        _textField = [[UITextField alloc] initWithFrame:CGRectZero];        
        _textField.backgroundColor          = [UIColor whiteColor];    

        self.backgroundColor                = [UIColor whiteColor];            
        self.contentView.backgroundColor    = [UIColor whiteColor];

        self.backgroundView = [[UIImageView alloc] init];        

        // not sure which of these should be set to opaque to ensure to meet criteria #4
        // 4. Make your UITableViewCell's layer opaque (same goes for the content view if you have one)
        self.backgroundView.opaque = YES;
        self.layer.opaque = YES;
        self.opaque = YES;        
        self.contentView.opaque = YES;        

        [self.contentView addSubview:_textField];
    }
}

- (void)layoutSubviews
{    
    CGRect textFieldFrame = CGRectMake(10, 2, 278, 40);
    self.textField.frame = textFieldFrame;

    [super layoutSubviews];
}

- (void)updateRowBackground:(UIImage *)rowBackground
{
    ((UIImageView *)self.backgroundView).image = rowBackground;        
}

1 个答案:

答案 0 :(得分:0)

如果您在每次调用cellForRowAtIndexPath时停止切换每个单元格的背景图像,我认为您会看到显着的性能提升。

听起来你有三种细胞(“顶部”,“中间”和“底部”)。您可以停止重复使用它们,因此每次使用时都必须重置背景图像。

相反,您可以使用不同的标识符初始化表格单元格的实例,具体取决于它们在表格中的位置。这样,您将创建具有“顶部”标识符的单个单元格,具有“底部”标识符的单个单元格以及具有“中间”标识符的许多单元格。然后,您只能在初始化单元格时设置其背景图像。只要您尝试重复使用具有适当标识符的单元格,您就不再需要每次都更改其背景图像。