Cómo optimizar la representación de UITableViewCell, al usar CGContextDrawLinearGradient

Tengo un UITableView donde bash get el mejor performance de desplazamiento posible.

La celda no contiene ninguna subvención, todo se hace en el método drawRect.

Cada celda tiene una línea blanca en la parte superior, una línea gris en la parte inferior y un gradiente lineal entre la parte superior e inferior. Además de este background, hay un text y una image.

Puedo ver en el uso de instrumentos que la porción principal (> 50%) del time de ejecución cuando se desplaza viene del dibujo del gradiente lineal. En realidad, casi todo eso proviene de la llamada a CGContextDrawLinearGradient.

¿Hay una buena manera de optimizar esto? Estoy pensando, ya sea en caching el gradiente lineal de alguna manera, o tal vez dibujarlo de otra manera … Tal vez dibujar un píxel de ancho y luego estirarlo?

Aquí hay algunos de mis códigos:

- (void)drawRect:(CGRect)rect { [self drawCellBackground:rect]; [self drawSeparator:rect]; .... } - (void)drawCellBackground:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); CGColorRef notQuiteWhiteColor = [UIColor colorWithRed:245.0/255.0 green:245.0/255.0 blue:245.0/255.0 alpha:1.0].CGColor; CGColorRef lightGrayColor = [UIColor colorWithRed:235.0/255.0 green:235.0/255.0 blue:235.0/255.0 alpha:1.0].CGColor; drawLinearGradient(context, rect, notQuiteWhiteColor, lightGrayColor); } 

De un file .c separado:

 void drawLinearGradient(CGContextRef context, CGRect rect, CGColorRef startColor, CGColorRef endColor) { CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGFloat locations[] = { 0.0, 1.0 }; NSArray *colors = [NSArray arrayWithObjects:(id)startColor, (id)endColor, nil]; CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (CFArrayRef) colors, locations); CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect)); CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect)); CGContextSaveGState(context); CGContextAddRect(context, rect); CGContextClip(context); CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0); CGContextRestoreGState(context); CGGradientRelease(gradient); CGColorSpaceRelease(colorSpace); } 

Si definitivamente quieres seguir usando drawRect: (que creo que ofrece un mejor performance que las vistas separadas en dispositivos más antiguos), ¿por qué no procesar tu gradiente en una image CGImage o UIImage, luego usar eso para dibujar -drawRect:?

Además, puede crear su gradiente de antemano:

 static CGGradientRef GetCellBackgroundGradient() { static CGGradientRef gradient = NULL ; if ( !gradient ) { gradient = // create your CGGradientRef here } return gradient; } 

Para get un código de alto performance, desea preasignar tantas cosas (memory / objects) como sea posible.

¿Estás reutilizando correctamente las celdas de vista de tabla? Si es así, en este caso, creo que será mejor utilizar subenviaturas en la vista de tabla en lugar de hacer todo el dibujo en drawRect: Al usar subyenes, y suponiendo que el gradiente es el mismo para todas las celdas, el gradiente solo tendría que ser dibujado una vez por celda reutilizable. Cuando se recicla con contenido nuevo, solo las vistas de text e image deberán actualizarse en lugar de tener que dibujar el degradado nuevamente.