这是一个相当简单的例子,无论如何可能不会产生太大的影响,但是说我在绘制渐变的视图中有这个绘图代码:
@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
我意识到这是一个非常微不足道的例子,但是如果我有更复杂的值可以重用,你可以想象出这个问题。是否有必要缓存这些内容,或者Cocoa-Touch基本上是否通过CALayers为您执行此操作?
以下是缓存的含义示例:
@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
你可以在这里看到权衡;特别是如果我有很多这样的观点,它可能最终会用这种技术占用更多的内存,而前者的绘图性能可能更差。但是,我甚至不确定是否需要进行权衡,因为我不知道Cocoa在幕后做了什么。谁能解释一下?
答案 0 :(得分:1)
唯一“缓存”是drawRect:
消息的结果。它被缓存直到无效,在这种情况下,再次调用该消息。
Cocoa和Cocoa-Touch不会缓存您在方法中使用的对象。您可以自己缓存它们,就像在第二个示例中所做的那样。但是,我建议使用诸如Instruments之类的分析器来测试这样的优化,以确保您不会因为代码过于复杂而没有太多的好处。
答案 1 :(得分:0)
每个UIView都有自己的屏幕外绘图缓冲区,因此移动UIView或改变其可见性不会导致UIView被重绘。如前所述,有一些特定的实例会触发重绘,但只要不引起重绘,就不应该调用drawRect例程。 (作为一个实验,尝试使用NSLog调用启动drawRect例程,以便在调用它时进行监视。)通过限制绘图实际发生的次数,这将使您更快地进行“快速”绘图。
您还应该能够使用像Shark这样的性能测量工具来查看您的绘图程序所花费的时间,以及花费最多时间的内容。特别是这种分析有助于防止缓存某些您认为可能非常昂贵的东西,但实际上并非如此,导致您在极少的性能上花费时间和复杂性。