I'm trying to build an app that use layers, my app structure is
UIView --> UIScrollView --> UIView --> LayersView (Custom UIView)
--> UIImageView
I want to add multiple layers to the LayersView, so I've build a custom CALayer
that use UIBezierPath
to draw a set of points.
CALayerBezierPath.h
#import <QuartzCore/QuartzCore.h>
@interface CALayerBezierPath : CALayer {
NSMutableArray *pointsArray;
}
@property (nonatomic, retain) NSMutableArray *pointsArray;
- (void) initVariables;
- (void) addNewPoints:(CGPoint)newPoint;
@end
CALayerBezierPath.m
#import "CALayerBezierPath.h"
@implementation CALayerBezierPath
@dynamic pointsArray;
-(void)drawInContext:(CGContextRef)ctx {
NSLog(@"CALayerBezierPath - drawInContext");
if ([pointsArray count] > 0) {
UIColor *color = [UIColor redColor];
[color set];
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:[[pointsArray objectAtIndex:0] CGPointValue]];
for (int x = 1; x < [pointsArray count]; x++) {
[path addLineToPoint:[[pointsArray objectAtIndex:x] CGPointValue]];
}
[path closePath]; // Implicitly does a line between p4 and p1
[path fill]; // If you want it filled, or...
[path stroke]; // ...if you want to draw the outline.
}
}
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
NSLog(@"drawLayer");// It's never called, i don't know why
}
- (void) initVariables {
pointsArray = [[NSMutableArray alloc] init];
}
- (void) addNewPoints:(CGPoint)newPoint {
[pointsArray addObject:[NSValue valueWithCGPoint:newPoint]];
}
@end
When I'm initiating a new layer in my LayrsView, I'm using this code:
self.layer.backgroundColor = [UIColor whiteColor].CGColor;
self.layer.cornerRadius = 20.0;
self.layer.frame = CGRectInset(self.layer.frame, 0, 0);
for (PlansClass *pclass in layersContent) {
CALayerBezierPath *sublayer = [CALayerBezierPath layer];
[sublayer initVariables];
NSDictionary* json = [pclass.listOfPoints objectFromJSONString];
float largerX = 0; float largerY = 0;
float smallerX = 10000; float smallerY = 10000;
for (NSDictionary *dic in json) {
[sublayer addNewPoints:CGPointMake([[[json objectForKey:dic] objectForKey:@"x"] floatValue], [[[json objectForKey:dic] objectForKey:@"y"] floatValue])];
if (largerX < [[[json objectForKey:dic] objectForKey:@"x"] floatValue]) {
largerX = [[[json objectForKey:dic] objectForKey:@"x"] floatValue];
}
if (smallerX > [[[json objectForKey:dic] objectForKey:@"x"] floatValue]) {
smallerX = [[[json objectForKey:dic] objectForKey:@"x"] floatValue];
}
if (largerY < [[[json objectForKey:dic] objectForKey:@"y"] floatValue]) {
largerY = [[[json objectForKey:dic] objectForKey:@"y"] floatValue];
}
if (smallerY > [[[json objectForKey:dic] objectForKey:@"y"] floatValue]) {
smallerY = [[[json objectForKey:dic] objectForKey:@"y"] floatValue];
}
}
sublayer.frame = CGRectMake(smallerX, smallerY, largerX - smallerX, largerY - smallerY);
sublayer.backgroundColor = [UIColor redColor].CGColor;
[self.layer addSublayer:sublayer];
[sublayer setNeedsDisplay];
}
The problem is whenever the app lunch, it's give me this error:
2012-09-13 08:05:47.648 abcd[20744:707] CALayerBezierPath - drawInContext
Sep 13 08:05:47 ipad-5 abcd[20744] <Error>: CGContextSetFillColorWithColor: invalid context 0x0
Sep 13 08:05:47 ipad-5 abcd[20744] <Error>: CGContextSetStrokeColorWithColor: invalid context 0x0
Sep 13 08:05:47 ipad-5 abcd[20744] <Error>: CGContextSaveGState: invalid context 0x0
Sep 13 08:05:47 ipad-5 abcd[20744] <Error>: CGContextSetFlatness: invalid context 0x0
Sep 13 08:05:47 ipad-5 abcd[20744] <Error>: CGContextAddPath: invalid context 0x0
Sep 13 08:05:47 ipad-5 abcd[20744] <Error>: CGContextDrawPath: invalid context 0x0
Sep 13 08:05:47 ipad-5 abcd[20744] <Error>: CGContextRestoreGState: invalid context 0x0
Sep 13 08:05:47 ipad-5 abcd[20744] <Error>: CGContextSaveGState: invalid context 0x0
Sep 13 08:05:47 ipad-5 abcd[20744] <Error>: CGContextSetLineWidth: invalid context 0x0
Sep 13 08:05:47 ipad-5 abcd[20744] <Error>: CGContextSetLineJoin: invalid context 0x0
Sep 13 08:05:47 ipad-5 abcd[20744] <Error>: CGContextSetLineCap: invalid context 0x0
Sep 13 08:05:47 ipad-5 abcd[20744] <Error>: CGContextSetMiterLimit: invalid context 0x0
Sep 13 08:05:47 ipad-5 abcd[20744] <Error>: CGContextSetFlatness: invalid context 0x0
Sep 13 08:05:47 ipad-5 abcd[20744] <Error>: CGContextAddPath: invalid context 0x0
Sep 13 08:05:47 ipad-5 abcd[20744] <Error>: CGContextDrawPath: invalid context 0x0
Sep 13 08:05:47 ipad-5 abcd[20744] <Error>: CGContextRestoreGState: invalid context 0x0
Also, I've tried to NSLog
the ctx
in the drawInContext
methods and it gives me this:
2012-09-13 08:05:47.650 abcd[20744:707] <CGContext 0x15d950>
So, Where is the problem, why is the context is invalid, why i can't draw in my custom CALayer
?
The problem is I've didn't push the context ctx
, I was trying push & pop. so the solution is as simple as putting this line in the if statement in drawInContext
UIGraphicsPushContext(ctx);
Everything works.