Ваша догадка верна, на самом деле это отличный способ оптимизировать рисование. Я сделал это сам, где у меня были большие статические фоны, которые я хотел избежать, чтобы перерисовывать, когда элементы перемещались сверху.
Все, что вам нужно сделать, это добавить 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:
и предотвратить анимацию с помощью возврат нулевого действия:
- (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;
}