Search code examples
iosshadowuibezierpathstroke

UIBezierPath's shadow: how to hide the stroke's shadow?


I'm trying to draw a UIBezierPathShape in iOS7 then apply a shadow. This works great except that when I stroke the path, the stroke shows up behind the shape. How can I rectify this?

Code:

- (void)drawDiamondWithCount:(NSUInteger)count inRect:(CGRect)rect {
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    UIGraphicsPushContext(ctx);
    UIEdgeInsets insets = UIEdgeInsetsMake(cardEdgeInsetTop, cardEdgeInsetRight, cardEdgeInsetBottom, cardEdgeInsetLeft);
    CGRect insetsRect = UIEdgeInsetsInsetRect(rect, insets);

    CGFloat shapeHeight = insetsRect.size.height / (double) count;
    CGRect shapeRect;
    for (NSUInteger i = 0; i < count; ++i) {
        // Get the rect for the single shape
        int numRemainingShapes = count - i - 1;
        CGFloat remainingBottomSpace = numRemainingShapes * shapeHeight;
        insets = UIEdgeInsetsMake(i * shapeHeight + shapeEdgeInsets, 0, remainingBottomSpace + shapeEdgeInsets, 0);
        shapeRect = UIEdgeInsetsInsetRect(insetsRect, insets);
        UIBezierPath *path = [self getDiamondPath:shapeRect];
        [[UIColor redColor] setFill];
        [[UIColor blackColor] setStroke];
        UIGraphicsPushContext(ctx);
        CGContextSetShadow(ctx, CGSizeMake(5, 2), 5);
        [path fill];
        UIGraphicsPopContext();
        //[path stroke];
    }
    UIGraphicsPopContext();
}

This gives me what I want, minus the stroke This gives me what I want, minus the stroke

Uncommenting [path stroke] gives me this. I want the stroke, but don't want to see it behind the shape.

enter image description here


Solution

  • I suspect that instead of UIGraphicsPushContext and UIGraphicsPopContext, I think you want CGContextSaveGState and CGContextRestoreGState:

    // create context and configure
    
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    [[UIColor redColor] setFill];
    [[UIColor blackColor] setStroke];
    
    // create path
    
    UIBezierPath *path = ...;
    path.lineJoinStyle = kCGLineJoinMiter;
    path.lineWidth = 2.0;
    
    // fill the center with shadow
    
    CGContextSaveGState(ctx);
    CGContextSetShadow(ctx, CGSizeMake(5, 2), 5);
    [path fill];
    CGContextRestoreGState(ctx);
    
    // stroke border without shadow
    
    CGContextSetLineWidth(ctx, 2.0);
    [path stroke];
    

    With UIGraphicsPushContext and UIGraphicsPopContext you get:

    line shadow

    With CGContextSaveGState and CGContextRestoreGState you get:

    enter image description here