2

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");
Jas999
  • 111
  • 6

2 Answers2

2

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");
Jas999
  • 111
  • 6
0

The reason you can't access the path property is because layer.presentationLayer is a property of CALayer and is itself of type CALayer, not CAShapeLayer. However, if the layer is of type CAShapeLayer it is, from my experience, safe to layer.presentationLayer to CAShapeLayer, after which you can access the path property.

Elte Hupkes
  • 2,773
  • 2
  • 23
  • 18