Situation: need to find which layer the user has touched.
Problem: Apple says we should use [CALayer presentationLayer] to do hit-testing, so that it represents what is actually on screen at the time (it captures info mid-animation etc).
...except: presentationLayer does NOT return the original layers, it returns copies of them ... so: the hitTest will return a brand new CALayer instance that is not equivalent to the original.
How do we find which actual CALayer was hit?
e.g.
CALayer* x = [CALayer layer];
CALayer* y = [CALayer layer];
[self.view.layer addSublayer: x];
[self.view.layer addSublayer: y];
...
CALayer* touchedLayer = [self.view.layer.presentationLayer hitTest:touchPoint];
...but, is touchedLayer "x", or is it "y"?
if( touchedLayer == x ) // this won't work, because touchedLayer is - by definition from Apple - a new object
Adam's answer is correct and helped me out. Here's the code that I used that may help someone else out.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint touchPoint = [(UITouch*)[touches anyObject] locationInView:self];
CALayer *touchedLayer = [self.layer.presentationLayer hitTest:touchPoint]; // is a copy of touchedLayer
CALayer *actualLayer = [touchedLayer modelLayer]; // returns the actual layer
NSLog (@"touchedLayer: %@", touchedLayer);
NSLog (@"actualLayer: %@", actualLayer);
}
Ah! Just figured this out, reading a mailing list post on a different problem with CALayer.
After calling [CALayer presentationLayer], and working with the "presentation clone" of the layer-tree, you can take any object in that tree, and call [CALayer modelLayer] on it to get back the original reference object at the same position in the original tree.
This reference is stable (tested - it works).
Apple's docs are a bit ... obscure ... on this one. And they imply it will "sometimes" fail ("...results are undefined") - but it's good enough for me for now.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With