Search code examples
ioscashapelayer

Can I access a CAShapeLayer's path property in the presentation layer?


I have a UIView subview called "starfish". It's backing layer is a CAShapeLayer who's path strokes a starfish shape. I want to do hit testing on this shape in my view controller within the enclosed path and not the view's rectangle. This is no problem, I simply call CGPathContainsPoint() on the CAShapeLayer path property in my view controller's touchesBegan and hit testing works.

CGPoint p = [[touches anyObject] locationInView:self.view];
CGPoint q = [self.view convertPoint:p toView:self.starfish];

if (CGPathContainsPoint([(CAShapeLayer*)self.starfish.layer path], NULL, q, true))
    NSLog(@"Success");
else
    NSLog(@"Fail");

If however the view is animating, moving from A to B, the same hit testing would need to be accessing the CAShapeLayer's path in the presentation layer but I can't seem to be ables to access this.

// Not working during animation
if (CGPathContainsPoint([(CAShapeLayer*)self.starfish.layer.presentationLayer path], NULL, q, true))
    NSLog(@"Success");
else
    NSLog(@"Fail");

Solution

  • Well I found a solution that works. I create a new CAShapeLayer with the same path and frame (based on the presentation layer) of the CAShapelayer I am testing for in touchesBegan.

    CGPoint p = [[touches anyObject] locationInView:self.view];
    
    CGRect rect = [(CAShapeLayer*)self.starfish.layer.presentationLayer frame];
    
    CAShapeLayer *shape = [CAShapeLayer layer];
    shape.path = [(CAShapeLayer*)self.starfish.layer path];
    shape.frame = rect;
    
    CGPoint q = [self.view.layer convertPoint:p toLayer:shape];
    
    if (CGPathContainsPoint(shape.path, NULL, q, true))
        NSLog(@"Success");
    else
        NSLog(@"Fail");