Pergunta

I have a UITableView and I have created a custom cell to display my table. I have 6 UILables displayed and although I have only 20 records to show, it is very slow when I scroll.

This is how my - tableView: cellForRowAtIndexPath: looks like:

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CustomCellIdentifier = @"CustomCellIdentifier";

    HistoryCell *cell = (HistoryCell *)[tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier];

    if (cell == nil) { 
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"HistoryCell" owner:nil options:nil];

        for (id oneObject in nib)
            if ([oneObject isKindOfClass:[UITableViewCell class]])
                cell = (HistoryCell *) oneObject;
    }

    NSArray *object;
    object = [cours objectForKey: [NSString stringWithFormat:@"%d", indexPath.section]];
    History *rowData = [object objectAtIndex:indexPath.row];

    if (rowData.month == 99) {
        cell.hour.frame = CGRectMake(10, 0, 135, 35);
        cell.data.hidden = YES;
        cell.hour.textColor = [UIColor blackColor];
        cell.hour.font = [UIFont fontWithName:@"Verdana" size:17];
    } else {
        cell.data.hidden = NO;
        cell.hour.frame = CGRectMake(10, 16, 135, 19);
        cell.hour.textColor = [UIColor grayColor];
        cell.hour.font = [UIFont fontWithName:@"Verdana" size:12];
    }

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"d (EEEE)"];
    [formatter setLocale:self.selectedLanguageLocale];
    NSString *stringFromDate = [formatter stringFromDate:rowData.data];
    [formatter release];

    cell.data.text = stringFromDate;
    cell.hour.text = rowData.ora;

    float Var1  = [rowData.Var2 floatValue];
    float Var2  = [rowData.Var2 floatValue];

    cell.R1.text = [self floatToStringFormat: [rowData.R1 floatValue]];
    cell.R2.text = [self floatToStringFormat: [rowData.R2 floatValue]];

    if (Var1 <= 0) {
        cell.Var1.textColor = [UIColor greenColor];
    } else {
        cell.Var1.textColor = [UIColor redColor];
    }
    if (Var2 <= 0) {
        cell.Var2.textColor = [UIColor greenColor];
    } else {
        cell.Var2.textColor = [UIColor redColor];
    }
    cell.Var1.text = [self floatToStringFormat:Var1];
    cell.Var2.text = [self floatToStringFormat:Var2];

    cell.selectionStyle = UITableViewCellSelectionStyleGray;
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

    return cell;
}

The reason for running that slow on scroll is because of all the things I am doing here (NSDateFormatter, CGMakeRect, floatToStringFormat...) or is there something wrong with reusing cells?

floatToStringFormat is a function to format a number to 4 decimals:

- (NSString *)floatToStringFormat:(float)number{
    NSNumberFormatter *myFloat = [[NSNumberFormatter alloc] init]; 
    [myFloat setFormatterBehavior:NSNumberFormatterBehavior10_4]; 
    [myFloat setNumberStyle:NSNumberFormatterDecimalStyle];
    [myFloat setRoundingMode:NSNumberFormatterRoundHalfUp];
    [myFloat setMinimumFractionDigits:4];
    [myFloat setMaximumFractionDigits:4];
    NSString *res = [myFloat stringFromNumber:[NSNumber numberWithFloat:number]];
    [myFloat release];
    return res;
}
Foi útil?

Solução

Creating and setting up formatter objects is an expensive operation indeed, so I'd start with reusing your formatter objects since they are the same on each function call. So either make them static variables or instant variables in your data source class and create the following way:

//static variable case
NSDateFormatter *formatter = nil;
if (!formatter){
   formatter = [[NSDateFormatter alloc] init];
   [formatter setDateFormat:@"d (EEEE)"];
   [formatter setLocale:self.selectedLanguageLocale];
}
NSString *stringFromDate = [formatter stringFromDate:rowData.data];
...

Outras dicas

Firstly, you are using two different identifiers: CustomCellIdentifier and BanciHistoryCellIdentifier.

Secondly, do you really need to do everything after NSArray *object; every time a new cell is displayed? Because if you don't, you should move it to the if (cell == nil) { block.

From my experience the drawing of table view cells is significantly slowed down if you have three or more subviews (also depends on the device and the views though). Try to directly draw the content in drawRect: instead of using subviews, this should speed things up.

What are you doing here:

if (cell == nil) { 
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"HistoryCell" owner:nil options:nil];

        for (id oneObject in nib)
            if ([oneObject isKindOfClass:[UITableViewCell class]])
                cell = (HistoryCell *) oneObject;
    }

Go read the documentation on how to do this properly. Secondly, if this is taking too long to convert the dates and numbers to strings then store the string values instead, and turn them into values when you need to modify them.

Do you have the CellIdentifier set in Interface builder? It must match exactly what you are using in code. Set a breakpoint where it loads the cell from the nib and make sure it's reusing cells when you scroll.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top