我正在制作一个自定义 NSView 对象,该对象的某些内容经常更改,而某些内容的更改频率则要低得多。事实证明,变化较少的部分需要最多的时间来绘制。我想做的是在不同的层中渲染这两个部分,这样我就可以分别更新一个或另一个,从而避免我的用户出现缓慢的用户界面。
我该怎么做呢?我还没有找到很多关于这类事情的好教程,也没有人谈论在 CALayer 上渲染 NSBezierPaths。任何人的想法?
我正在制作一个自定义 NSView 对象,该对象的某些内容经常更改,而某些内容的更改频率则要低得多。事实证明,变化较少的部分需要最多的时间来绘制。我想做的是在不同的层中渲染这两个部分,这样我就可以分别更新一个或另一个,从而避免我的用户出现缓慢的用户界面。
我该怎么做呢?我还没有找到很多关于这类事情的好教程,也没有人谈论在 CALayer 上渲染 NSBezierPaths。任何人的想法?
你的预感是对的,这实际上是一种优化绘图的好方法。我自己完成了一些大型静态背景,当元素移动到顶部时我想避免重绘这些背景。
您需要做的就是CALayer
为视图中的每个内容项添加对象。要绘制图层,您应该将视图设置为每个图层的委托,然后实现该drawLayer:inContext:
方法。
在该方法中,您只需绘制每一层的内容:
- (void)drawLayer:(CALayer*)layer inContext:(CGContextRef)ctx
{
if(layer == yourBackgroundLayer)
{
//draw your background content in the context
//you can either use Quartz drawing directly in the CGContextRef,
//or if you want to use the Cocoa drawing objects you can do this:
NSGraphicsContext* drawingContext = [NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:YES];
NSGraphicsContext* previousContext = [NSGraphicsContext currentContext];
[NSGraphicsContext setCurrentContext:drawingContext];
[NSGraphicsContext saveGraphicsState];
//draw some stuff with NSBezierPath etc
[NSGraphicsContext restoreGraphicsState];
[NSGraphicsContext setCurrentContext:previousContext];
}
else if (layer == someOtherLayer)
{
//draw other layer
}
//etc etc
}
当您想要更新其中一个图层的内容时,只需调用[yourLayer setNeedsDisplay]
. 然后这将调用上面的委托方法来提供图层的更新内容。
请注意,默认情况下,当您更改图层内容时,Core Animation 为新内容提供了一个很好的淡入淡出过渡。但是,如果您自己处理绘图,您可能不希望这样做,因此为了防止在图层内容更改时默认动画淡入,您还必须实现actionForLayer:forKey:
委托方法并通过返回 null 来防止动画行动:
- (id<CAAction>)actionForLayer:(CALayer*)layer forKey:(NSString*)key
{
if(layer == someLayer)
{
//we don't want to animate new content in and out
if([key isEqualToString:@"contents"])
{
return (id<CAAction>)[NSNull null];
}
}
//the default action for everything else
return nil;
}