I have used both UIBezierPath
and CAShapeLayer
before. But almost every time in conjunction with filling the object contained within the path with col
The main problem is that you can't really fill the outside of a shape, since there's no generic way to define what that means. What you need to do is first plot a path around the "outside" of your shape, and then add the circle as a subpath. How you do that depends on which fill rule you want to use. EvenOdd is the easiest:
CAShapeLayer *myLayer = (CAShapeLayer*) self.layer;
UIBezierPath *testPath = [UIBezierPath bezierPathWithRect:self.bounds];
[testPath appendPath:[UIBezierPath bezierPathWithOvalInRect:(CGRect){{100, 100}, 100, 100}]];
myLayer.fillRule = kCAFillRuleEvenOdd;
myLayer.path = testPath.CGPath;
myLayer.fillColor = [UIColor whiteColor].CGColor;
NonZero is a little bit harder because you have to force the path to be counter-clockwise which isn't an option for most of the UIBezierPath convenience methods:
CAShapeLayer *myLayer = (CAShapeLayer*) self.layer;
UIBezierPath *testPath = [UIBezierPath bezierPathWithRect:self.bounds];
UIBezierPath *counterClockwise = [UIBezierPath bezierPathWithArcCenter:CGPointMake(100, 100) radius:100 startAngle:0 endAngle:M_PI clockwise:NO];
[counterClockwise appendPath:[UIBezierPath bezierPathWithArcCenter:CGPointMake(100, 100) radius:100 startAngle:M_PI endAngle:0 clockwise:NO]];
[testPath appendPath:counterClockwise];
myLayer.fillRule = kCAFillRuleNonZero;
myLayer.path = testPath.CGPath;
myLayer.fillColor = [UIColor redColor].CGColor;
Depending on how you're constructing your actual path it may not make a difference either way.
If you haven't seen it already, the winding rules documentation has some nice diagrams that I find helpful.