Skotch
Skotch

Reputation: 3091

Setting mask on CALayer breaks hitTest

I have a CALayer with hitTesting that works fine. The code is something like this:

- (void)setup
{
    _maskLayer = [CAShapeLayer layer];
    _maskLayer.fillColor = [UIColor whiteColor].CGColor;
    _maskLayer.path = somePath;

    _theLayer.frame = CGRectMake(0, 0, size.width, size.height);
    // Taps work fine if we do not apply the mask
    // _theLayer.mask = _maskLayer;
}

- (IBAction)tapOnView:(UITapGestureRecognizer *)sender
{
    CGPoint point = [sender locationInView:theView];
    CALayer *subLayer = [_theLayer.presentationLayer hitTest:point].modelLayer;

    if (subLayer != _theLayer && subLayer != nil) {
        // Do something with the sublayer which the user touched
    }
}

The problem is that if I uncomment the line with the mask, my hit testing always returns nil. Why does the mask kill hit testing? It appears correct visually.

Upvotes: 1

Views: 255

Answers (2)

Fernando Mata
Fernando Mata

Reputation: 492

I used the accepted answer but still had some issue because you should use bounds just to prevent your mask not showing if your layer is other than 0,0 Also, this is the swift solution:

theLayer.frame = CGRecti(x: 0, y, 0: width: size.width, height:size.height) 

maskLayer.frame = theLayer.bounds
theLayer.mask = maskLayer

Upvotes: 0

Skotch
Skotch

Reputation: 3091

It turns out that hit testing requires the point to be inside the bounds of the CALayer, but what is not documented is that it also has to be inside the bounds of the mask. So I changed my code like this and it worked:

    _theLayer.frame = CGRectMake(0, 0, size.width, size.height);

    // Apply a mask
    _maskLayer.frame = _theLayer.frame;
    _theLayer.mask = _maskLayer;

It took me a few hours to figure this out, so I wanted to share.

Upvotes: 2

Related Questions