I’m trying out the animation stuff with the iPhone and I have a small app that has circles falling from the top of the screen to the bottom. I added the UIViewAnimationOptionAllowUserInteraction option to the animation and set userInteractionEnabled = YES on both my sub views and my main view. I am generating the subview programmatically everytime my NSTimer fires, which makes the circles.
The problem I am having is that even if I implement - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event on my main view and my subviews, the event only ever fires on the main view regardless of how hard or how many times I smash the falling circles.
How do I get that event to fire on my circles instead? Why doesn’t the touch fire on the view on top?
The problem is that when you perform a “tween” animation with Core Animation (which occurs implicitly when you use the
UIViewanimation methods), the new value is immediately applied to what’s known as the model layer tree.The animation is committed to Core Animation, and the next time the main run loop occurs, Core Animation does the necessary rendering to make it look as if an animation is occurring. In reality, though, the model values of your view (e.g., its
frameortransformproperties) are changed immediately.Try tapping at the bottom of the screen where the buttons land (assuming they finish on screen). If you do this, it should respond to the interaction event as you expect.
You could manually change the frame of your circles by constantly firing a timer and applying small changes at each step. This, however, is likely not ideal.
Another option is to make use of your view’s layer’s
presentationLayermethod. This layer represents the state of the layer at any point in time, as we see it on the screen. Off the top of my head, I imagine that your main view’s touch handling method can iterate through each subview and check to see if the touch point intersects the frame of the subview’s layer’s presentation layer. If it does, then that means someone “touched” your subview.I should note that
presentationLayerreturnsid, because the presentation layer may beCALayeror any of its subclasses. So, for example, if you’re usingCAShapeLayer, then-presentationLayerwill return aCAShapeLayer. Still, it’s fine to just cast it to aCALayersince all you care about for the purposes of this task is to check itsframeproperty.