Ceci est un exemple assez simple et ne serait probablement pas faire beaucoup de différence de toute façon, mais dire que j'ai ce code de dessin en vue de tracer un gradient:Est-il nécessaire de mettre en cache les opérations courantes pour -drawRect: sur l'iPhone?
@interface SomeView : UIView
@end
@implementation SomeView
- (void)drawRect:(CGRect)rect
{
const CGContextRef ctx = UIGraphicsGetCurrentContext();
// Set fill color to white
CGContextSetGrayFillColor(ctx, 1.0f, 1.0f);
CGContextFillRect(ctx, rect);
// Create a fancy, albeit ugly, orange gradient
const CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
const CGFloat components[] = { 1.0, 0.5, 0.4, 1.0, // Start color
0.8, 0.8, 0.3, 1.0 }; // End color
CGGradientRef gloss;
gloss = CGGradientCreateWithColorComponents(rgbColorSpace, components, NULL, 2);
CGColorSpaceRelease(rgbColorSpace);
// Draw the gradient
const CGPoint endPoint = {rect.origin.x,
rect.origin.y + floor(rect.size.height/2.0f)};
CGContextDrawLinearGradient(ctx, gloss, rect.origin, endPoint, 0);
CGGradientRelease(gloss);
}
@end
Je sais que cela est un exemple très négligeable , mais vous pouvez imaginer l'inquiétude si j'avais des valeurs plus complexes à réutiliser. Est-il nécessaire de les mettre en cache, ou est-ce que Cocoa-Touch le fait pour vous avec CALayers?
Voici un exemple de ce que je veux dire par la mise en cache:
@interface SomeView : UIView
{
CGGradientRef gloss;
}
@end
@implementation SomeView
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
// Create a fancy, albeit ugly, orange gradient only once here instead
const CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
const CGFloat components[] = { 1.0, 0.5, 0.4, 1.0, // Start color
0.8, 0.8, 0.3, 1.0 }; // End color
CGGradientRef gloss;
gloss = CGGradientCreateWithColorComponents(rgbColorSpace, components, NULL, 2);
CGColorSpaceRelease(rgbColorSpace);
}
return self;
}
- (void)dealloc
{
CGGradientRelease(gradient);
[super dealloc];
}
- (void)drawRect:(CGRect)
{
const CGContextRef ctx = UIGraphicsGetCurrentContext();
// Set fill color to white
CGContextSetGrayFillColor(ctx, 1.0f, 1.0f);
CGContextFillRect(ctx, rect);
// Draw the gradient
const CGPoint endPoint = {rect.origin.x,
rect.origin.y + floor(rect.size.height/2.0f)};
CGContextDrawLinearGradient(ctx, gloss, rect.origin, endPoint, 0);
}
@end
Vous pouvez évidemment voir le compromis entre ici; Surtout si j'avais beaucoup de ces vues, cela pourrait prendre plus de mémoire avec cette technique par rapport aux performances de dessin éventuellement pire dans le premier. Cependant, je ne suis même pas sûr si est beaucoup d'un compromis parce que je ne sais pas quelle magie Cocoa fait dans les coulisses. Quelqu'un pourrait-il expliquer?
Quand est-il invalidé? – Michael
+1 Quant au moment où il est invalidé, beaucoup de choses peuvent l'invalider, et il est possible d'invalider seulement une partie de la vue (c'est pourquoi -drawRect: vous passe un CGRect pour vous dire quelle partie a été invalidée). Vous appelez -setNeedsDisplay l'invalide bien sûr. Lorsque la vue apparaît sur l'écran. Lorsque l'état de la vue change (en surbrillance par exemple). Lorsque la taille de la vue change. Parfois pendant le défilement (bien qu'il y ait quelques optimisations de cache bitmap là). –
Dans d'autres commentaires, Apple vous déconseille de dessiner des dégradés si vous pouvez l'aider. L'iPhone n'est pas toujours assez rapide pour le faire. La recommandation d'Apple est d'utiliser des images. Les dégradés sont souvent traités avec des images d'un seul pixel qui sont ensuite étirées horizontalement pour remplir la zone souhaitée. –