I have a UIView
subclass with a custom drawRect:
method which does some expensive calculations to build a path and draws it using CGContextStrokePath()
on the current context.
If my view has a size (x, y)
, I want to do my custom drawing on (0, 0), (x/2, y)
and then fill the (x/2, 0), (x, y)
area with a mirrored image of the first half.
What is the simplest/fastest way of doing this, other than manually duplicating the points to be drawn? Maybe rendering the half view to a bitmap image context and using that one to render on both halves of the current image context? The content is animated, so drawRect:
is roughly executed 60 times per second.
One efficient way of doing this is to do the draw operations on the context of a CGLayer
, and then use the layer to draw on the current UIView
's context.
See Core Graphics Layer Drawing on the Quartz 2D Programming Guide for more details.
Basically you would do this:
- (void)drawRect:(CGRect)rect
{
const CGFloat viewWidth = view.bounds.size.width;
const CGFloat viewHeight = view.bounds.size.height;
CGContextRef viewContext = UIGraphicsGetCurrentContext();
CGLayerRef layer = CGLayerCreateWithContext(viewContext, CGSizeMake(viewWidth/2, viewHeight), 0);
CGContextRef layerContext = CGLayerGetContext(layer);
// Draw to the layerContext
// using CGContextStrokePath() or whatever
CGContextDrawLayerAtPoint(viewContext, CGPointZero, layer);
CGContextTranslateCTM(viewContext, viewWidth, 0);
CGContextScaleCTM(viewContext, -1, 1);
CGContextDrawLayerAtPoint(viewContext, CGPointZero, layer);
CGLayerRelease(layer);
}
Additionally, you can store the CGLayerRef
as an ivar of UIView
so you don't recreate it every frame.
This solution works great in my case, but two caveats:
CGLayers
, as stated here.CGLayers
you have to follow the steps detailed here