2012-09-11 73 views
2

我有一個UITableView加載令人難以置信的慢(慢糖漿,也許)我可以告訴它是由於UITableViewCells設置自定義背景圖像在我分組的UITableView由ViewController擁有。用自定義UITableViewCells(破記錄)改善ViewController加載速度

我覺得作爲推薦在這個其他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的電池手柄內部的
  • 細胞的層設置爲不透明
  • 小區標識符被重用
  • 不是從筆尖裝入電池文件

基本上,我想用不同的頂部,中部和底部行背景圖片,這取決於哪一行的類型類型,它的樣式各表的部分的行。任何人都可以提出一個更好的方式來在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;   
} 
+0

我很困惑,但每個細胞都有不同的背景?你有多少個細胞?如果你有很多具有不同背景的單元,那麼它們應該被動態加載。通過在viewdidload中加載所有內容,您可以使界面等待所有事情的準備就緒。另外如果你正在調試,你有很多單元格,請確保你沒有NSLOG的東西,增加了加載時間很多。 – Pochi

+0

我有3種不同的背景類型。每個部分的頂行單元格應該有1個類型(它有一個向下的曲線),中間的行有另一個(標準圖像),最後,每個部分的底部行有第三種類型(這個圖像有一個向上的曲線)。 –

+0

我共有15行,分爲4個部分。 –

回答

0

我想你會看到一個顯著的性能增益,如果停止開關每一個細胞的背景圖像上每次調用cellForRowAtIndexPath

這聽起來像你有三種單元格(「頂部」,「中間」和「底部」)。您可以不必重複使用它們,因此必須在每次使用時重置其背景圖像。

取而代之,您可以使用不同的標識符來初始化表格單元格的實例,具體取決於它們在表格中的位置。這樣,您將創建一個帶有「頂部」標識符的單個單元格,帶有「底部」標識符的單個單元格以及具有「中間」標識符的多個單元格。您只能在初始化單元格時設置其背景圖像。只要您嘗試重複使用具有適當標識符的單元格,您就不再需要每次都更改其背景圖像。

+0

由於我有2種不同的細胞類型,我會有6個細胞ID變異。我的印象是,擁有許多不同的細胞類型對於性能來說也不是很好。在CocoaWithLove網站上提供的代碼示例中,我只看到了1個cellId類型,但是根據indexPath.row顯示了不同的背景。 –

+0

更多的單元格標識符可能會導致表視圖在內存中保留更多單元格的實例,但這不一定會影響性能。我的印象是馬特在CocoaWithLove上的例子是演示如何定製單元格外觀,而不一定是高性能單元格創建的指南。由於您現在似乎有一個真正的性能問題,並且已將其歸因於更新這些背景圖像的成本,所以我認爲這是嘗試消除該問題的合理實驗。 – Jonah

+0

只是想確保我明白這一點:當你有一個自定義的頂部,中間和底部行背景,你將有3個不同的單元格標識符爲每個單元類型出列。如果您的單元格保存異質數據或UI元素,則每個單元格類型都會有其他唯一的單元格ID類型。 –

相關問題